预期输出:
Child = 2
Parent = 1
我的代码:
class Parent{
int a;
public:
void display(){
a = 1;
cout << "Parent = " << a << endl;
}
};
class Child:public Parent{
int b;
public:
void display(){
b = 2;
cout << "Child = " << b << endl;
}
};
int main()
{
Parent *p = new Child();
Child c;
//write your code here
/* My solution :
c.display();
Parent* a = &c;
a->display();
*/
}
我利用静态绑定成功调用了父类的display()成员函数
但是,我想知道这个问题是否有更好的解决方案。
使用此行Parent *p = new Child();
的目的是什么?它是指向构造函数的指针吗?
该行与Parent *p = new Child;
有什么区别?
答案 0 :(得分:4)
这里有几点要说明:
Child
不会覆盖任何内容,它只是隐藏了基类方法。覆盖将需要virtual
成员函数,并且您可以通过添加override
关键字来验证方法是否实际上覆盖了基类函数。这两个类都不是多态的,因为任何地方都没有虚拟方法。
由于您的类不是多态的,因此您将永远只有静态绑定,没有动态绑定。 (您正确识别了这种情况)。
要调用在派生类中被重写或隐藏的基类函数,请在该调用之前添加基类名称和::
,如下所示:
class Child : public Parent{
int b;
public:
void display(){
Parent::display();
}
};
// or
int main()
{
Child c;
c.Parent::display();
}
在代码中Parent *p = new Child();
和Parent *p = new Child;
之间没有区别,它们都调用默认构造函数来初始化新的子对象。对于类似int
的类型,存在差异,new int;
创建未初始化的int
对象,new int();
(或new int{};
)将其初始化为零。
答案 1 :(得分:1)
如何在C ++中调用父类的重写函数?
在示例中,您实际上并未覆盖任何功能。只能覆盖虚拟成员函数,而display
是非虚拟成员函数。
我利用静态绑定成功调用了父类的display()成员函数
您的解决方案之所以有效,是因为其中不涉及任何重写或虚拟功能。调用隐藏成员函数的另一种方法是使用范围解析运算符:
c.Parent::display();
即使函数是虚拟的,也将使用静态绑定。
使用此行
Parent *p = new Child();
的目的是什么?
它在您的程序中似乎没有任何用途。通常,new
用于从免费存储区动态分配对象。
请注意,除非使用delete
显式取消分配内存,否则内存将被泄漏。同样不是delete p
会具有不确定的行为,因为它指向析构函数为非虚拟的基数。
它是指向构造函数的指针吗?
不。 p
指向在免费商店中创建的动态对象。
该行与
Parent *p = new Child;
有什么区别?
不带括号,则使用默认的初始化语法。括号为空时,您可以使用值初始化。
对于简单可构造的类(例如Parent
),默认初始化将默认初始化成员。对于整数成员,这将使成员保持未初始化状态。值初始化将改为对成员进行值初始化,对于整数,这意味着初始化为零。
对于非平凡可构造类(例如Child
),默认值初始化和值初始化都会调用默认构造函数。