C++中子类的变量能不能覆盖父类的变量?
刚学了继承技术,还不太清楚一些东西。比如下面代码:#include<string>#include<iostream>usingnamespacestd;classPar...
刚学了继承技术,还不太清楚一些东西。比如下面代码:
#include <string>
#include <iostream>
using namespace std;
class Parent
{
public:
Parent() :mStr("Parent") {};
virtual void Show();
protected:
string mStr;
};
class Children : public Parent
{
public:
Children() : mStr("Children"){};
protected:
string mStr;
};
void Parent::Show() { cout<<mStr<<endl; }
int main(int argc, char* argv[])
{
Children tmp;
tmp.Show();
return 0;
}
我本来预想上面的代码会显示"Children",但是结果是"Parent"。
然后把 cout<<mStr<<endl; 改为了 cout<<this->mStr<<endl; ,但是结果一样。
尝试给变量mStr加上 virtual 关键字,但是编译不通过。
如果把父类的Show函数写为虚函数,那么子类覆盖的代码是一模一样的,又不符合继承的优点。
那么究竟要怎么做才好? 展开
#include <string>
#include <iostream>
using namespace std;
class Parent
{
public:
Parent() :mStr("Parent") {};
virtual void Show();
protected:
string mStr;
};
class Children : public Parent
{
public:
Children() : mStr("Children"){};
protected:
string mStr;
};
void Parent::Show() { cout<<mStr<<endl; }
int main(int argc, char* argv[])
{
Children tmp;
tmp.Show();
return 0;
}
我本来预想上面的代码会显示"Children",但是结果是"Parent"。
然后把 cout<<mStr<<endl; 改为了 cout<<this->mStr<<endl; ,但是结果一样。
尝试给变量mStr加上 virtual 关键字,但是编译不通过。
如果把父类的Show函数写为虚函数,那么子类覆盖的代码是一模一样的,又不符合继承的优点。
那么究竟要怎么做才好? 展开
4个回答
展开全部
区分成员变量情况,有以下几种情况:
1 子类和父类没有同名成员变量。
此种情况下不会出现任何情况的覆盖。
2 在父类中,有virtual修饰的虚成员变量,在子类中有与其同名同类型的成员变量。
此种情况下,子类变量会覆盖父类变量。
3 在父类中,存在有与子类同名同类型的成员变量,但没有virtual修饰。
此时不会覆盖,但是会重写。即子类中访问成员变量时,访问的是子类的,父类的会被隐藏。但是通过父类名直接调用仍可以使用父类该变量。不属于覆盖,被称为重写。
1 子类和父类没有同名成员变量。
此种情况下不会出现任何情况的覆盖。
2 在父类中,有virtual修饰的虚成员变量,在子类中有与其同名同类型的成员变量。
此种情况下,子类变量会覆盖父类变量。
3 在父类中,存在有与子类同名同类型的成员变量,但没有virtual修饰。
此时不会覆盖,但是会重写。即子类中访问成员变量时,访问的是子类的,父类的会被隐藏。但是通过父类名直接调用仍可以使用父类该变量。不属于覆盖,被称为重写。
展开全部
从内存分配的角度上来看,子类继承时,先分配了父类的内存,再分配子类的内存,所以子类中同时存在着父类的空间和新的空间两个部分。当你使用父类函数的时候,显然会使用的是父类中的变量。在子类中增加同名的变量,会使子类的成员变量将父类的覆盖,却不会使父类的函数中的成员发生覆盖。
所以最好的办法就是不在子类中增加新的变量,而是直接使用父类中的变量。
将
Children() : mStr("Children"){};
protected:
string mStr;
改为
Children() {mStr = "Children"};
所以最好的办法就是不在子类中增加新的变量,而是直接使用父类中的变量。
将
Children() : mStr("Children"){};
protected:
string mStr;
改为
Children() {mStr = "Children"};
追问
如果mStr被定义为常量那怎么办?
或者说父类中的一个函数被不同的子类使用,而此函数需要使用 对应不同子类的不同常量。
追答
~呃~ 如果一定要父类使用子类的变量的话,在父类的成员函数中增加一个传参的函数,构造函数里面使用它从子类传入参数。这样子也不是很方便的,还不如重载一个函数。
总之,父类使用子类的变量是很少用的,不同的子类有不同的要求尽量用重载函数的形式使用。
如果均相同就如我一开始讲的方法。
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
子类的mStr和父类的mStr是不同的东西,你在子类中调用:
mStr
this->mStr
都是子类的变量,
Parent::mStr
才是父类的变量。
#include <assert.h>
class Parent
{
public:
Parent() : m_nVal(0) {}
virtual void Show()
{
assert(m_nVal == 0);
}
protected:
int m_nVal;
};
class Son : public Parent
{
public:
Son() : m_nVal(1) {}
virtual void Show()
{
assert(Parent::m_nVal == 0);
assert(m_nVal == 1);
assert(this->m_nVal == 1);
}
private:
int m_nVal;
};
int _tmain(int argc, _TCHAR* argv[])
{
Son s;
s.Show();
return 0;
}
mStr
this->mStr
都是子类的变量,
Parent::mStr
才是父类的变量。
#include <assert.h>
class Parent
{
public:
Parent() : m_nVal(0) {}
virtual void Show()
{
assert(m_nVal == 0);
}
protected:
int m_nVal;
};
class Son : public Parent
{
public:
Son() : m_nVal(1) {}
virtual void Show()
{
assert(Parent::m_nVal == 0);
assert(m_nVal == 1);
assert(this->m_nVal == 1);
}
private:
int m_nVal;
};
int _tmain(int argc, _TCHAR* argv[])
{
Son s;
s.Show();
return 0;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
是可以的,因为子类和父类有不同的作用域
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询