gpt4 book ai didi

c++ - 使用派生类的数据调用基类的方法 : is there an elegant way to do this?

转载 作者:行者123 更新时间:2023-11-28 02:51:55 26 4
gpt4 key购买 nike

我正在研究 C++ 库。这个库将包含一堆简单的对象,它们彼此非常相似。

我已经为我的对象定义了一个简单的接口(interface):

struct ICommand_v1
{
virtual void GetCommandName(wchar_t* nameBuffer, size_t* nameBufferSize) = 0;
virtual void GetCommandGUID(wchar_t* guidBuffer, size_t* guidBufferSize) = 0;
virtual bool Execute(int argc, wchar_t* argv[]) = 0;
};

我的难点在于 GetCommandNameGetCommandGUID 函数。每个子类的它们应该几乎相同;有一点完整性检查,然后返回命令的内置名称或 GUID。一个 GetCommandName 与另一个,或一个 GetCommandGUID 与另一个的唯一区别是返回值。我不想在我的库将使用的大约两打对象中重复这些方法,所以我尝试为我的对象创建一个基类:

struct ICommandImplementation_v1: ICommand_v1
{
public:
virtual void GetCommandName(wchar_t* nameBuffer, size_t* nameBufferSize)
{
size_t workingBufferSize = *nameBufferSize;

if ((nameBuffer == nullptr) || (wcslen(commandName) > workingBufferSize))
{
*nameBufferSize = wcslen(commandName);
return;
}

wcsncpy(nameBuffer, commandName, workingBufferSize);
*nameBufferSize = wcslen(commandName);
}

virtual void GetCommandGUID(wchar_t* guidBuffer, size_t* guidBufferSize)
{
size_t workingBufferSize = *guidBufferSize;

if ((guidBuffer == nullptr) || (wcslen(commandGUID) > workingBufferSize))
{
*guidBufferSize = wcslen(commandGUID);
return;
}

wcsncpy(guidBuffer, commandGUID, workingBufferSize);
*guidBufferSize = wcslen(commandGUID);
}

virtual bool Execute(int argc, wchar_t* argv[])
{
return true;
}

private:
const wchar_t* commandName = TEXT("Default");
const wchar_t* commandGUID = TEXT("Default");
};

然后,我尝试让我的对象覆盖基类的 commandNamecommandGUID 属性:

struct AboutCommand: ICommandImplementation_v1
{
public:
bool Execute(int UNUSED(argc), wchar_t* UNUSED(argv[]))
{
return true;
}

private:
const wchar_t* commandName = TEXT("AboutCommand");
const wchar_t* commandGUID = TEXT("01eba0e6-81b9-4fa7-a9f3-407d330da9b3");
};

当然,这实际上并没有奏效。创建 AboutCommand 对象并调用其 GetCommandName 返回“Default”。这是有道理的 - 我们实际上是在调用 ICommandImplementation_v1GetCommandName,而 ICommandImplementation_v1 不知道 AboutCommand或其阴影 commandName

在这一点上,我想我可能必须在 ICommandImplementation_v1 中创建一个简单的 protected 方法,该方法采用命令名称以及缓冲区/缓冲区大小(ICommandImplementation_v1: :GetRealCommandName(const wchar_t* commandName = TEXT("Default"), wchar_t* nameBuffer, size_t* nameBufferSize),然后 AboutCommandGetCommandName 只会用它自己的 commandName 调用这个函数。不过,这对我来说似乎很笨拙;有没有更简洁、更优雅的方法来做到这一点?

最佳答案

最简单的方法是将两个字符串作为参数传递给基类:

struct ICommandImplementation_v1: ICommand_v1
{
public:
ICommandImplementation_v1(wchar_t const* name, wchar_t const* guid):
commandName(name),
commandGUID(guid)
{
}
void GetCommandName(wchar_t* nameBuffer, size_t* nameBufferSize)
{
size_t workingBufferSize = *nameBufferSize;

if ((nameBuffer == nullptr) || (wcslen(commandName) > workingBufferSize))
{
*nameBufferSize = wcslen(commandName);
return;
}

wcsncpy(nameBuffer, commandName, workingBufferSize);
*nameBufferSize = wcslen(commandName);
}

void GetCommandGUID(wchar_t* guidBuffer, size_t* guidBufferSize)
{
size_t workingBufferSize = *guidBufferSize;

if ((guidBuffer == nullptr) || (wcslen(commandGUID) > workingBufferSize))
{
*guidBufferSize = wcslen(commandGUID);
return;
}

wcsncpy(guidBuffer, commandGUID, workingBufferSize);
*guidBufferSize = wcslen(commandGUID);
}

virtual bool Execute(int argc, wchar_t* argv[])
{
return true;
}

private:
const wchar_t* commandName = TEXT("Default");
const wchar_t* commandGUID = TEXT("Default");
};

struct AboutCommand: ICommandImplementation_v1
{
public:
AboutCommand():
ICommandImplementation_v1(TEXT("AboutCommand"),
TEXT("01eba0e6-81b9-4fa7-a9f3-407d330da9b3"))
{}

bool Execute(int UNUSED(argc), wchar_t* UNUSED(argv[]))
{
return true;
}
};

一般来说,你想要的是"template method" .不是在基类中定义两个私有(private)字段,而是定义两个私有(private)纯虚方法,它们被称为 GetCommandGUID 和 GetCommandName 并返回特定于子类的值:

struct ICommandImplementation_v1: ICommand_v1
{
public:
void GetCommandName(wchar_t* nameBuffer, size_t* nameBufferSize)
{
size_t workingBufferSize = *nameBufferSize;

if ((nameBuffer == nullptr) || (wcslen(commandName()) > workingBufferSize))
{
*nameBufferSize = wcslen(commandName());
return;
}

wcsncpy(nameBuffer, commandName(), workingBufferSize);
*nameBufferSize = wcslen(commandName());
}

void GetCommandGUID(wchar_t* guidBuffer, size_t* guidBufferSize)
{
size_t workingBufferSize = *guidBufferSize;

if ((guidBuffer == nullptr) || (wcslen(commandGUID()) > workingBufferSize))
{
*guidBufferSize = wcslen(commandGUID());
return;
}

wcsncpy(guidBuffer, commandGUID, workingBufferSize);
*guidBufferSize = wcslen(commandGUID);
}

virtual bool Execute(int argc, wchar_t* argv[])
{
return true;
}

private:
virtual const wchar_t* commandName() = 0;
virtual const wchat_t* commandGUID() = 0;
};

struct AboutCommand: ICommandImplementation_v1
{
public:
bool Execute(int UNUSED(argc), wchar_t* UNUSED(argv[]))
{
return true;
}

private:
const wchar_t* commandName() {return TEXT("AboutCommand")}
const wchar_t* commandGUID() {TEXT("01eba0e6-81b9-4fa7-a9f3-407d330da9b3")}
};

请帮自己一个忙,不要使用 wchar_t* 而是使用 std::wstring 作为字符串。

关于c++ - 使用派生类的数据调用基类的方法 : is there an elegant way to do this?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22847423/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com