C++中指向派生类的基类指针————————经典

#include <iostream>

class A
{
public:
 void a1(){
  std::cout << "a1" << std::endl;
 }
 virtual void vt(){
  std::cout << "a" << std::endl;
 }
private:
 void a2(){
  std::cout << "a2" << std::endl;
 }
protected:
 void a3(){
  std::cout << "a3" << std::endl;
 } 
};

class B : public A
{
public:
 void b1(){
  std::cout << "b1" << std::endl;
 }
 virtual void vt(){
  std::cout << "b" << std::endl;
 }
private:
 void b2(){
  std::cout << "b2" << std::endl;
 }
protected:
 void b3(){
  std::cout << "a3" << std::endl;
 } 
};


int main()
{
 B *pb = new B;
 A *pA = pb; 

 pA->vt();  // 正确:输出为 b (多态性) 
 pA->a1();  // 正确:输出为 a1 
// pA->a2();  // 错误:pA无权访问私有成员函数 a2
// pA->a3();  // 错误:pA无权访问保护成员函数 a3

// pA->b1();  // 错误:b1 不是 类A 的成员函数 
// pA->b2();  // 错误:b2 不是 类A 的成员函数 
// pA->b3();  // 错误:b3 不是 类A 的成员函数 
 
 std::cout << std::endl;
 pb->vt();  // 正确:输出为 b (多态性)
 pb->a1();  // 正确:输出为 a1 
// pb->a2();  // 错误:pb无权访问基类的私有成员函数 
// pb->a3();  // 错误:b无权访问基类的保护成员函数

 pb->b1();  // 正确:输出为 b1 
// pb->b2();  // 错误:pb无权访问自身的私有成员函数 
// pb->b3();  // 错误:b无权访问自身的保护成员函数
 
 
 B b; 
 A &rb = b;
 
 std::cout << std::endl;
 rb.vt();  // 正确:输出为 b (多态性) 
 rb.a1();  // 正确:输出为 a1 
// rb.a2();  // 错误:rb无权访问私有成员函数 
// rb.a3();  // 错误:pA无权访问保护成员函数 a3

// rb.b1();  // 错误:b1 不是 类A 的成员函数 
// rb.b2();  // 错误:b2 不是 类A 的成员函数 
// rb.b3();  // 错误:b3 不是 类A 的成员函数

 std::cout << std::endl;
 b.vt();   // 正确:输出为 b (多态性)
 b.a1();   // 正确:输出为 a1 
// b.a2();   // 错误:b无权访问基类的私有成员函数 
// b.a3();   // 错误:b无权访问基类的保护成员函数

 b.b1();   // 正确:输出为 b1 
// b.b2();   // 错误:b无权访问自身的私有成员函数 
// b.b3();   // 错误:b无权访问自身的保护成员函数 
  
 return 0;
}

结论:
1、对于派生类和基类的访问范围:
(1)派生类可以直接访问自身的公有成员函数和基类中的公有成员函数。
(2)私有成员变量、私有成员函数只能通过调用类中的公有成员函数来访问,不能通过对象名直接访问。派生类不能访问基类的私有成员函数。
(3)保护成员变量、保护成员函数也只能通过调用类中的公有成员函数来访问,不能通过对象名直接访问。派生类可以通过公有成员函数访问基类的保护成员函数。

2、关于指向派生类的基类指针和基类引用的访问范围:
(1)指向派生类的基类指针或者引用,其类型仍然属于基类类型,而不是派生类类型,尽管它指向的是派生类。其访问范围受其基类类型影响,因此只能访问基类中可以访问的类型。
(2)对于虚函数,使用指向派生类的基类指针或基类引用访问时,将会体现出多态性,调用的是实际上是派生类的对应函数。
(3)对于指向派生类的基类引用,虽然说引用通常是被引用对象的一个别名,但这里,基类引用的访问范围与被引用对象的访问范围明显是不一样的!

一句话这样总结:当基类类型的指针或引用使用派生类的对象时,它对虚函数的调用,实际上是调用了被指向对象类的函数。注意,取决于被指向对象。
当它对非虚函数调用时,会使用基类自身的函数。

原文地址:https://www.cnblogs.com/hao02171990/p/3287986.html