C++ 经过一些处理后,如何调用父构造函数?
我想在调用父构造函数之前进行一些处理。下面的例子说明了为什么我想这样做,尽管为了清楚起见,我已经把它稍微简化了一点。真正的父构造函数正在进行一些渲染,但是让我们先尝试解决这个问题 本质上,当父构造函数调用重写函数,但子构造函数的数据尚未设置时,问题就出现了。我该如何解决这个问题C++ 经过一些处理后,如何调用父构造函数?,c++,C++,我想在调用父构造函数之前进行一些处理。下面的例子说明了为什么我想这样做,尽管为了清楚起见,我已经把它稍微简化了一点。真正的父构造函数正在进行一些渲染,但是让我们先尝试解决这个问题 本质上,当父构造函数调用重写函数,但子构造函数的数据尚未设置时,问题就出现了。我该如何解决这个问题 class BaseClass { public: int myNumber; BaseClass(){ myNumber = 0; this->printNumber
class BaseClass {
public:
int myNumber;
BaseClass(){
myNumber = 0;
this->printNumber();
}
virtual void printNumber(){
printf("My number is %d\n", this->myNumber);
}
}
class ChildClass : BaseClass {
public:
float childNumber;
ChildClass(float myNumber) : BaseClass() {
this->childNumber = myNumber;
}
void printNumber(){
printf("My number is %f\n", this->childNumber);
}
}
当父构造函数调用重写函数时会出现问题
不,那永远不会发生。在BaseClass
的构造函数中,它的动态类型也是BaseClass
,因此printNumber()
调用将解析为它自己的编号,而不是某个派生类。为什么?因为那时ChildClass
的构造函数还没有完成运行,所以它还没有被创建
正如@FredLarson所评论的,这里有关于这个主题的更多信息:就像上面其他人所说的,你不应该从构造函数调用虚拟成员。但为了解决您的问题,有一个成语可能会对您有所帮助,它叫base from member: 它的基本功能是利用基类按声明顺序初始化的事实。在初始化基类之前,您可以在单独的基类中执行需要执行的操作
class OtherBaseClass {
int Num;
OtherBaseclass(float num) : Num(num)
{
printf("My number is %d\n", this->Num);
}
};
class ChildClass : OtherBaseClass, BaseClass {
public:
float childNumber;
ChildClass(float myNumber) : OtherBaseClass(myNumber), BaseClass() {
....
请注意,基类的构造函数无法调用派生类的虚拟函数版本,即不会调用
ChildClass::printNumber()
function
也就是说,如果您想在基类的构造函数之前执行某些操作,一种方法是使用另一个基类,并将其置于另一个基类之前:
class RunMeFirst
{
public RunMeFirst()
{ printf("whatever...\n"); }
};
class ChildClass : private RunMeFirst, public BaseClass
{ /*...*/ };
在基类的构造函数之前运行以下几项:
- 参数初始化
- 虚拟基类的构造函数
- 早期的构造函数声明的其他基类
一种常用的解决方案称为“来自成员的基本习惯用法”,它涉及将成员移动到首先构造的新基类。是否必须在基类中实现呈现功能?你能不能用合成代替继承。使用组合将允许您轻松控制成员初始化顺序,例如:
#include <iostream>
class renderer
{
public:
renderer(int number)
{
std::cout << "Number is " << number << std::endl;
}
};
class foo
{
public:
foo()
: number_(12)
, renderer_(number_)
{
}
private:
int number_;
renderer renderer_;
};
int main()
{
foo bar;
}
#包括
类渲染器
{
公众:
渲染器(整数)
{
std::cout感谢@K-ballo指出了错误,正因为如此,我才能够稍微重新构造代码来做我想做的事情,但由于这也不是问题的技术正确答案,我将保留正确答案
class BaseClass {
public:
int myNumber;
BaseClass(bool initialize = true){
myNumber = 0;
if (initialize){
this->initialize();
}
}
void initialize(){
this->printNumber();
}
virtual void printNumber(){
printf("My number is %d\n", this->myNumber);
}
}
class ChildClass : BaseClass {
public:
float childNumber;
ChildClass(float myNumber) : BaseClass(false) {
this->childNumber = myNumber;
this->initialize();
}
void printNumber(){
printf("My number is %f\n", this->childNumber);
}
}
更多信息:+1感谢您指出我假设中的错误。然而,这并不是标题中所述问题的答案,因此我将此标记为“答案”会感到很遗憾。+1,但请注意,这个具体的答案指出,printNumber()如果从基类构造函数调用,基类中的
将从基类实现中调用。在本例中,这肯定是正确的,因此为+1。但是,如果您的memberFn()
在基类中是纯虚拟的。下面是上述习惯用法的一个增强实现:您可以从构造函数调用虚拟函数。