在没有模板的构造函数中访问覆盖的字段 [英] Access overridden field in constructor without templates
问题描述
我无法从父C ++构造函数访问子类中重写的字段,并且我不能使用模板,因为上游项目不使用它们.
I can't access field overridden in child class from parent C++ constructor and I can not use templates, because upstream project doesn't use them.
这是正在工作的Python原型,我尝试在C ++中重新实现.该代码包含两个驱动程序类-一个子级和一个父级,并且父级在初始化期间打印该类的name
.
This is working Python prototype that I try to reimplement in C++. The code contains two driver classes - one child and one parent, and parent prints name
of the class during initialization.
class Driver(object):
name = "Unknown"
def __init__(self):
print(self.name)
class SpecificDriver(Driver):
name = "Specific"
def __init__(self):
super(SpecificDriver, self).__init__()
Driver()
SpecificDriver()
这将两个字符串打印到控制台
This prints two strings to console
Unknown
Specific
在C ++中看起来无法访问覆盖的name
,因为此时name
不存在-
Looks like in C++ can't access overridden name
, because the name
doesn't exist at this point - Call child method from parent constructor. So maybe there is another way to get driver name
printed on initialization?
更新(2018):该问题的原标题是在C ++中初始化时在没有模板的情况下打印覆盖的子字段",并且由于范围太广而被关闭.
UPDATE (2018): The original title for this question was "Print overridden child field during initialization in C++ without templates" and it was closed as too broad.
推荐答案
尽管您要求不使用模板来执行此操作,但这是从基类构造函数执行此操作的唯一方法.
Despite you're asking to do this without templates, it's the only way to do this from a base class constructor.
以下是应如何操作的示例:
Here's a sample how it should be done:
struct IDriver {
// Public virtual API:
virtual void func1() = 0;
// ...
virtual ~IDriver() {}
};
template<typename Derived>
class Driver : public IDriver {
public:
Driver() {
std::cout << "Driver" << std::endl;
std::cout << static_cast<Derived*>(this)->name() << std::endl;
}
};
class SpecificDriver : public Driver<SpecificDriver> {
public:
// Public virtual API:
virtual void func1();
std::string name() const { return "SpecificDriver"; }
// or use typeid(SpecificDriver).name() if you prefer
};
int main() {
SpecificDriver sd;
}
至于您的评论:
是否可以像@tobspr方法中一样使用其他init()函数,但是将名称设为字段而不是函数调用?
Is it possible to use additional init() function as in @tobspr method, but making name a field instead of function call?
好吧,由于类名仍然是这些类的静态属性,因此您可以使用如下的static const
字段:
Well, since the class name is a static property of these classes anyway, you can use a static const
field like follows:
template<typename Derived>
class Driver : public IDriver {
public:
Driver() {
std::cout << name << std::endl;
std::cout << Derived::name << std::endl;
}
private:
static const std::string name;
};
template<typename Derived>
const std::string Driver<Derived>::name = "Driver";
class SpecificDriver : public Driver<SpecificDriver> {
public:
static const std::string name;
};
const std::string SpecificDriver::name = "SpecificDriver";
int main() {
SpecificDriver sd;
}
甚至简化使用typeid()
:
#include <iostream>
#include <string>
#include <typeinfo>
template<typename Derived>
class Driver {
public:
Driver() {
std::cout << typeid(*this).name() << std::endl;
std::cout << typeid(Derived).name() << std::endl;
}
};
class SpecificDriver : public Driver<SpecificDriver> {
};
int main() {
SpecificDriver sd;
}
这篇关于在没有模板的构造函数中访问覆盖的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!