基类和派生类非虚函数和成员变量的同名

本文探讨了C++中子类与父类同名成员函数及数据成员的现象,包括static成员的不同处理方式。通过实例说明了如何通过类型限定解决隐藏问题,并展示了不同指针类型对成员访问的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于子类和父类如果拥有同名的data member 或者non virtual 成员函数,会如何处理?如果data member是static类型的又有何不同?(实际上体现了对继承的深刻理解
    对于这样的同名non virtual 函数或者 成员,实际上由指针或者对象的类型决定了访问的具体是哪个?如果使用子类类型的对象或指针,则只能看到子类里的哪个函数或者成员,对于父类里的函数则会产生遮蔽(隐藏)现象(任何时候子类中重新定义了基类中的函数,基类中所有同名的重载函数都自动隐藏了),如果想访问父类成员,必须加上父类的名称限定,【实现模型】也就是说实际上编译器在实现中自动地对这种重名现象进行了处理,给父类对象加上了一个限定词合成了一个新的名称。但是如果没有发生这种重名现象,子类类型的对象或指针,依然可以正常访问从父类继承下来的那些成员。 static 数据成员也同理。
    如果使用基类类型的对象或指针(即使用派生类对象地址来初始化),则永远只能看到基类里的函数和成员,不能显示访问子类的对象。
class Base 
{
	
public:
	Base():a(1){}
	virtual void func() {cout<<"Base"<<endl;}
	
	int f() const{
		cout<<"Base::f()\n";
		return 1;
	}

	int f(string str) const {cout<<str<<endl; return 1;}
	int a;
	static int  s;
};


class Derive : public Base

{

public:  
	Derive():a(2){}
	void func() {cout<<"Derive"<<endl;}
	/*
	int f() const{
		cout<<"Derive::f()\n";
		return 1;
	}
	*/
	
	void f() const{
		cout<<"void f() \n";
	}
	// 上面的两个f()不能同时存在一个类中,因为无法重载仅按返回类型区分的non-virtual函数;可放在其他从Base派生的类中
	
        int a;
	static int s;
};

int Base::s = 0;  //static变量初始化
int Derive::s = 1;

int main()
{
	Derive d;
	Derive *pa = &d;
	//一般成员变量
	cout<<pa->a<<endl;  //pa为Derive类型,由于基类和派生类有同名的a, 对基类中的a会隐藏,实际上是给父类的对象a加上了一个限定词。默认访问的是Derive类中的a = 2
	cout<<pa->Base::a<<endl;  // 若想访问基类的a,必须显示指定
	
        //static member  
	cout<<pa->s<<endl;  ///pa为Derive类型,对基类中的静态成员s隐藏,默认访问Derive的s
	cout<<pa->Base::s<<endl;  //显示访问Base的s
	
	//member function
 	pa->f(); // pa为Derive类型,Derive对f进行了重新定义,隐藏了基类中的所有f的重载版本;默认访问Derive的f
	pa->Base::f();  //显示访问Base的f

	// !!! pa->f("abc");  //派生类对non-virtual 函数进行改写(重新定义或参数列表,返回值改变)时,派生类中的函数会隐藏基类中的所有重载版本!!因此,不能访问基类的f(string){};
	pa->Base::f("abc");   //只能通过显示访问被隐藏的Base::f(string)
	
	Base *pb = &d;
	cout<<pb->a<<endl;  //pb为Base类型,默认且只能访问Base类中的a = 1;
	cout<<pb->s<<endl;  
	//!!!  cout<<pb->Derive::a<<endl;  // 出错,提示限定名不是Base或其基类的成员。因为父类指针pb是无法访问子类里的public成员变量或者函数的
	//可以使用强制转换static_cast<Derive*>(pb)实现;
	cout<<static_cast<Derive*>(pb)->s<<endl;  //pb强制转换为Derive型后,和pa一样,默认访问的是Derive的a = 2;
	cout<<pb->a<<endl;  //此时上面的转换失效,pb仍然还是Base* 类型。
  	
	cout<<pb->s<<endl;
	pb->f(); // 
	pb->f("123");
	//!!! pb->Derive::f();  //显示访问Derive的f,错误,pb为Base*,不能访问Derived的成员

	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值