我在C ++中有两个类,其中一个继承自另一个:
class A {
public:
virtual void Initialize(){
m_MyString = "Default value";
}
protected:
string m_MyString;
}
class B : public A {
public:
void Initialize(){
A::Initialize();
m_MyString = "New Value";
}
}
上述B级与此之间有区别吗?
class B : public A {
public:
void Initialize(){
A::Initialize();
A::m_MyString = "New Value";
}
}
看起来使用作用域操作符会导致字符串有垃圾,对吗?我想当它覆盖时,A :: m_MyString与B :: m_MyString不同。这甚至有意义吗?
我看到变量在A中设置,然后当我们返回B时,有垃圾。这与“隐藏”与被覆盖有关吗?
答案 0 :(得分:1)
您的代码在许多方面无效。它应该看起来像:
class A { // << errors were here
public:
virtual void Initialize(){
m_MyString = "Default value";
}
protected:
string m_MyString;
}; // << lost ;
class B : public A // << errors were here
{
public:
virtual void Initialize(){ // << virtual
A::Initialize(); // has no effect in the end
A::m_MyString = "New Value"; // same as `m_MyString = "New Value";`
}
}; // << lost ;
在上面的代码中,与m_MyString
没有区别。发布错误的实际代码。
如果你的代码如下:
class B : public A
{
public:
virtual void Initialize(){
// here is a difference
A::m_MyString = "New Value";
m_MyString = "New Value";
}
protected:
string m_MyString; // !!! overridden
};
然后存在差异,因为B
有两个m_MyString
实例:A::m_MyString
和B::m_MyString
。
答案 1 :(得分:1)
你是否从A的构造函数中调用Initialize()?
不建议在构造函数中调用虚方法。例如,如果A的构造函数看起来像
A::A() {
Initialize();
}
B的Initialize方法永远不会被调用。
查看您的实际代码会有很大帮助。
答案 2 :(得分:0)
这两个版本的B类没有区别。这是你看到垃圾的真实代码吗?
答案 3 :(得分:0)
编译器应该告诉您是否从构造函数调用虚函数。但如果没有,那肯定是个问题。
我认为你可以在派生类中创建一个虚函数final,但也许不是。无论是否明确定义范围,变量都应该相同,除非在派生类中有一个同名变量。
答案 4 :(得分:0)
如果这是你的代码的样子:
using namespace std;
class A
{
public:
virtual void Initialize()
{
m_MyString = "Default value";
}
protected:
string m_MyString;
};
class B : public A
{
public:
void Initialize()
{
A::Initialize();
m_MyString = "New Value";
}
void display()
{
cout<<m_MyString<<endl;
}
};
int main()
{
B b;
A a;
b.Initialize();
b.display();
return 0;
}
然后,您在问题中描述的B类的两个版本之间没有区别。我添加了显示功能只是为了使值清晰。根据您给出的类的定义,不会覆盖m_MyString。因此,m_MyString变量将为其分配“新值”,即类A和B都将共享变量m_MyString。
如果覆盖类B中的m_MyString,如
class B : public A
{
public:
void Initialize()
{
A::Initialize();
m_MyString = "New Value";
}
void display()
{
cout<<m_MyString<<endl;
}
protected:
string m_MyString;
};
然后B :: m_MyString的值将包含“New Value”,A :: m_MyString的值将包含“Default value”。
答案 5 :(得分:0)
看起来使用作用域操作符会导致字符串有垃圾,对吗?
不,这应该有效,并且在调用b.Initialize()之后m_MyString将具有“新值”。
我在想它覆盖时,A :: m_MyString与B :: m_MyString不同。是否 这甚至有意义吗?
不,当B类继承另一个A类时,B类的对象将具有两者的数据成员的并集。在这种情况下,只有一个m_MyString是A :: m_MyString。
我看到变量在A中设置,然后当我们返回B时,有垃圾。 这与“隐藏”与被覆盖?
有关
不,只有一个m_MyString实例。
您肯定需要阅读此内容 - http://www.openrce.org/articles/files/jangrayhood.pdf。