访问C++中模板参数派生类的虚拟成员函数



我可能只是忽略了什么或很愚蠢,在这种情况下我很抱歉,但我真的不知道如何访问虚拟成员函数(如果可能的话(。实际上,虚拟部分是关于可能的解决方案的第二个问题,我稍后将对此进行描述。以下是一些总结我的问题的示例代码:

class BaseClass
{
public:
virtual std::string ClassName()
{
return "BaseClass";
}
};
class DerivedClass : public BaseClass
{
public:
std::string ClassName()
{
return "DerivedClass";
}
};
template<class cT>
void StatusPrint(const std::string& message)
{
return cT.ClassName(); // Here's where my issue arises.
}

因此,我尝试用ct::替换cT.,然而,虽然这本身会导致编译器问题,但它也尝试访问BaseClass中的虚拟函数,但我想访问DerivedClass中的重写函数。

我想做的事情可能这样吗?

很抱歉我看起来很粗鲁,但您不能从void函数返回任何内容。显然,我们这里没有完整的故事。

你真的想要一个编译时解决方案吗

查看您的代码,className()似乎根本没有使用对象的状态。所以你可以把它做成static(而不是virtual(。这个问题可以通过来解决

template<class cT>
std::string StatusPrint(const std::string& message)  // returns string, not void
{
return cT::ClassName();    // :: if class name is static.
}

由于模板无法从其参数派生类型,因此您需要提供它,以便在编译时完全选择类:

cout<< StatusPrint<DerivedClass>("test"s)<<endl;

当您有一些实用程序类,并且希望在编译时配置要使用哪一个时,就会使用这种做法。

您想要动态解决方案吗

如果您希望在运行时使用动态解决方案,则需要使用一些对象,因为virtual需要一个在运行时知道其动态类型的对象。

然后它取决于上下文。一种解决方案是使用cT参数,具有参数推导的优点:

template<class cT>
std::string StatusPrint ( cT object, const std::string& message)
{
return object.ClassName(); // Here's where my issue arises.
}

然后你可以称之为:

DerivedClass test; 
...
cout<< StatusPrint(test, "test"s)<<endl;

在线演示

当然,它也可以使用一些全局对象(但模板的意义要小得多(,或者更好的是,如果您将StatusPrint((重构为此类的成员函数,则可以使用模板类中的对象。

我不确定你到底想做什么,但看看这是否更像:

std::string StatusPrint(BaseClass *instance) {
return instance->ClassName();
}

模板参数用于类型,虚拟继承需要指针。

DerivedClass derived;
std::cout << StatusPrint(&derived) << std::endl; // note the &

cT是一种类型,而不是对象。您只能在对象实例上调用函数(除非它们是静态函数,但这不是您在这里要做的(。您需要传入要打印出的对象的实例。例如

template<class T>
std::string StatusPrint(const T& obj, const std::string& message)
{
return obj.ClassName();
}

为了避免这种混淆,通常使用大写字母命名模板类型。

我不得不承认编译器的错误让人困惑,但它确实给了你一个暗示,cT有问题。这是说.之前发生的事情并不是它所期望的。

与GCC 9:

error: expected primary-expression before '.' token
24 |   return cT.ClassName();
|            ^

最新更新