精华内容
下载资源
问答
  • 隐藏是指:基类和派生类中有同名的成员变量或成员函数,那么派生类的成员变量、成员函数就将基类的隐藏(重定义)了。 如何调用隐藏的成员函数(或使用隐藏的成员变量)? 指定作用域 2 派生类的六个默认...

    1 隐藏(重定义)
    隐藏是指:在基类和派生类中有同名的成员变量或成员函数,那么派生类的成员变量、成员函数就将基类的隐藏(重定义)了。
    隐藏(重定义)
    如何调用隐藏的成员函数(或使用隐藏的成员变量)?
    隐藏——赋值
    指定作用域
    调用隐藏的成员
    2 派生类的六个默认成员函数
    在默认情况下,派生类的默认成员函数由基类的成员函数合成(具体实现见下面的代码)
    (1)构造函数
    子类的构造函数,继承了父类的构造函数,需要先调用父类的构造函数,再构造自己的成员
    对于子类中继承而来的父类的成员,一般可以采用匿名对象的方式进行初始化
    (2)拷贝构造
    对子类的拷贝构造,先将参数t中切片给子类中从父类继承而来的成员,再对子类中自己的成员进行拷贝构造。
    子类的拷贝构造
    (3)赋值运算符重载
    赋值运算符的函数均为operator=,所以明显子类和父类的赋值运算符重载函数的函数名一样,构成隐藏(重定义),在子类中调用父类的赋值运算符重载函数时需要指定作用域。
    (4)析构函数
    一般析构函数不显示的调用。
    虽然子类和父类的函数名不同,但在编译器中会对析构函数进行处理,全部变为函数名为distructor的函数,所以析构函数也构成隐藏(重定义),如果想要调用父类的析构函数,必须指定作用域。
    析构函数是先析构子类自己的成员,再调用父类的析构函数

    //派生类的六个默认成员函数(以日期类为例)
    class Date
    {
    public:
          Date(int year = 1900,int month = 1,int day = 1)
                :_year(year)
                ,_month(month)
                ,_day(day)
          {}
          Date(const Date& d)
                :_year(d._year)
                ,_month(d._month)
                ,_day(d._day)
          {}
          Date& operator=(const Date& d)
          {
                _year = d._year;
                _month = d._month;
                _day = d._day;
                return *this;
          }
          ~Date()
          {}
    
    private:
          int _year;
          int _month;
          int _day;
    };
    class Time :public Date
    {
    public:
          Time(int hour = 0, int minute = 0, int second = 0)
                :Date()               //构造函数:子类中从父类继承的成员,采用匿名对象的方式进行构造
                , _hour(hour)
                , _minute(minute)
                , _second(second)
          {}
          Time(const Time& t)
                :Date(t)            //“切片”
                , _hour(t._hour)
                , _minute(t._minute)
                , _second(t._second)
          {}
          Time& operator=(const Time& t) //与父类的operator构成重定义,需要指定Date的作用域调用operator=
          {
                if (this != &t)
                {
                      Date::operator=(t);
                      _hour = t._hour;
                      _minute = t._minute;
                      _second = t._second;
                }
                return *this;
          }
          ~Time()  //与父类的析构函数也构成重定义,需要指定作用域的调用,但是一般都不需要显示的调用
          {
                Date::~Date();
          }
    
    private:
          int _hour;
          int _minute;
          int _second;
    };
    

    3 定义一个不能被继承的类
    将构造函数定义为私有的
    a.对于父类中私有的成员,不论在哪种继承方式下对于子类而言都是不可见的;
    b.子类在构造时,必须先调用父类的构造函数,再构造自己的;
    c.不可见的成员是无法调用的,所以该类不能被继承。
    d.有一个需要注意的就是:当我们把构造函数定义为私有的,则不能生成该类的实例
    e.定义一个静态的公有方法,用于生成该类的实例

    //定义一个不能被继承的类
    class A
    {
    public:
          static A* GetInstance()
          {
                return new A();
          }
    private:
          A()
          {}
    };
    
    int main()
    {
          A* pa = A::GetInstance();
          return 0;
    }
    
    展开全文
  • 派生类中的默认成员函数2. 继承与友元、静态成员 1. 派生类中的默认成员函数 6个默认成员函数:构造函数、析构函数、拷贝构造函数、赋值重载、取地址重载(普通对象和const对象取地址) 派生类的构造函数必须...

    1. 派生类中的默认成员函数

    • 6个默认成员函数:构造函数、析构函数、拷贝构造函数、赋值重载、取地址重载(普通对象和const对象取地址)

    • 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员,如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显式调用;

    • 派生类拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化;

    • 派生类的operator=必须要调用基类的operator=完成基类的复制;

    • 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员;

    • 派生类对象初始化先调用基类构造再调用派生类构造;

    • 派生类对象析构清理先调用派生类析构,再调用基类的析构。

    在这里插入图片描述

    //成员初始化顺序,一定先初始化父类成员,后初始化子类成员
    class Person
    {
    public:
    	//构造函数
    	Person(int id=1, int age=16)
    		:_id(id)
    		, _age(age)
    	{
    		cout << "Person(int, int)" << endl;
    	}
    
    	//无缺省值构造函数
    	/*Person(int id, int age)
    		:_id(id)
    		, _age(age)
    	{
    		cout << "Person(int, int)" << endl;
    	}*/
    
    	//拷贝构造
    	Person(const Person& p)
    		:_id(p._id)
    		,_age(p._age)
    	{
    		cout << "Person(const Person&)" << endl;
    	}
    
    	//赋值运算符重载
    	Person& operator=(const Person& p)
    	{
    		if (this != &p)
    		{
    			_id = p._id;
    			_age = p._age;
    		}
    		cout << "Person& operator=(const Person& p)" << endl;
    		return *this;
    	}
    
    	//析构函数
    	~Person() {
    		cout << "~Person()" << endl;
    	}
    protected:
    	int _id;
    	int _age;
    };
    class Student :public Person
    {
    public:
    	//不能在子类的初始化列表中直接初始化父类的成员
    	//如果父类有默认构造,初始化列表可以不用显式调用父类的构造函数,编译器会自动调用父类构造
    	//如果父类没有默认构造,必须显式调用父类的一个构造函数
    	Student(int id,int age,int stuId)
    		:_stuId(stuId)
    	{
    		//Person(id, age);
    		cout << "Student(int, int, int)" << endl;
    	}
    
    	//父类无缺省值时
    	/*Student(int id, int age, int stuId)
    		:Person(id, age)
    		, _stuId(stuId)
    	{
    		cout << "Student(int, int, int)" << endl;
    	}*/
    	//拷贝构造的初始化列表中可以调用普通的父类构造函数
    	//也可以调用拷贝构造
    	Student(const Student& stu)
    		:Person(stu)
    		,_stuId(stu._stuId)
    	{
    		cout << "Student(const Student&)" << endl;
    	}
    
    	Student& operator=(const Student& stu)
    	{
    		if (this != &stu)
    		{
    			//父类的赋值和子类的赋值运算符构成同名隐藏,需要加上父类作用域
    			Person::operator=(stu);
    			//operator=(stu);递归调用自己,同名隐藏,直到栈溢出才停止
    			_id = stu._id;
    			_age = stu._age;
    			_stuId = stu._stuId;
    		}
    		cout << "Student& operator=(const Student& stu)" << endl;
    		return *this;
    	}
    	//析构
    	//编译器在任何情况下,都会自动调用父类的析构,所以不需要显式调用父类析构
    	~Student()
    	{
    		//~Person();子类析构和父类析构构成同名隐藏,析构函数底层的函数名:destruct
    		//Person::~Person();
    		cout << "~Student()" << endl;
    	}	
    private:
    	int _stuId;
    };
    void test()
    {
    	//子类的默认构造会自动调用父类的构造函数
    	//先父类后子类
    	Student stu(1, 2, 3);
    	//子类默认的拷贝构造会自动调用父类的拷贝构造
    	//如果子类显式定义了拷贝构造,子类的拷贝构造会自动调用父类的默认构造
    	Student copy(stu);
    	//赋值:子类的默认赋值运算符会自动调用父类的赋值运算符
    	//子类定义的赋值运算符不会自动调用父类的赋值运算符,除非显式调用
    	stu = copy;
    
    	//析构:子类默认的析构/显式调用都会自动调用父类的析构
    	//先子类后父类
    	Student stu1(1, 2, 3);
    }
    

    2. 继承与友元、静态成员

    • 友元关系不能继承,基类友元不能访问子类私有的和保护的成员。
    • 基类定义了static静态成员,则整个继承体系中只有一个这样的成员,无论派生多少个子类,都只有一个static成员实例。
    //基类的static成员在整个继承体中,被所有对象共享
    class A
    {
    public:
    	A()
    	{
    		++_a;
    	}
    public:
    	static int _a;
    };
    int A::_a = 0;
    class B :public A
    {};
    class C :public B
    {};
    void test()
    {
    	A a;
    	B b;
    	C c;
    	cout << a._a << endl;
    	cout << b._a << endl;
    	cout << c._a << endl;
    	cout << &a._a << endl;
    	cout << &b._a << endl;
    	cout << &c._a << endl;
    }
    

    在这里插入图片描述

    展开全文
  • 派生类B中的成员函数Show(),对基类A中成员函数Show()进行覆盖。 例子: #include using namespace std; class A { public: void Show() { cout<<"A::Show()"; } }; class B : public A { public: void ...

    用派生类B中的成员函数Show(),对基类A中的成员函数Show()进行覆盖。

    例子:

    #include <iostream>
    using namespace std;
    class A
    {
    public:
    	void Show() { cout<<"A::Show()"<<endl; }
    };
    class B : public A
    {
    public:
    	void Show() { cout<<"B::Show()"<<endl; }//在派生类中重新定义成员函数
    	void Display() { Show(); }
    };
    
    int main()
    {
    	A a;
    	B b;
    	a.Show();
    	b.Show();
    	b.Display();
    
    	return 0;
    }

    程序运行显示结果:



    如果想在派生类B的成员函数Display()中调用基类A的成员函数Show(),可以使用作用域限定符 '::',如下所示:

    void Display() { A::Show(); }  //调用基类A的成员函数SHow()

    展开全文
  • class A { protected:  A(){}  ~A(){} public:  virtual void print()  {  cout  } }; class B:public A { public:  B(){}  ~B(){} private:  virtual void print()  {  cout  } }

    看下面这个例子:

    class A
    {
    protected:
     A(){}
     ~A(){}
    public:
     virtual void print()
     {
      cout<<"A::print()!"<<endl;
     }
    };
    class B:public A
    {
    public:
     B(){}
     ~B(){}
    private:
     virtual void print()
     {
      cout<<"B::print()!"<<endl;
     }
    };
    int main()
    {
     //A obj;//ERROR
     B d;
     A *pB = &d;
     pB->print();
     return 0;
    }

    最后输出"B::print()!",调用的是派生类B中的私有成员函数

    print是一个虚函数,pB指向都内容是Derived,所以 pB->print() 调用的是Derivied::print()。
    至于private的问题,因为pB是指向Base的指针,调用Base的private函数是可以的(只不过Base::print()那个虚函数指针的内容是 Derivied::print())???这句话没看懂,实在不知道为什么会这样???

    展开全文
  • #include &lt;iostream&gt; using namespace std; /*有些基类的方法在派生...* 1: 直接在派生类中调用被覆盖的基类方法,如 Person::CheckPerson() ; * 2: 使用派生类对象调用被覆盖的基类方法,如 Tom.P...
  • C++派生类中与基类同名函数调用问题

    万次阅读 多人点赞 2016-11-11 22:26:14
    一、派生类,即子类函数与基类的函数的情况有以下三种。 1、不是同名函数 2、函数名相同,形参的个数或类型不同。 3、函数名相同,形参的个数和类型也相同。 二、接下来就这三种情况探讨子类调用基类函数的...
  • 多态的使用方法是当基类指针指向派生类对象时,可以直接调用派生类重写的虚函数,而不是基类的虚函数。实现方法也是老生常谈,通过每个对象的虚函数表指针,去找属于自己类的虚函数执行。那如果用派生类指针指向...
  • 当创建一个派生类的对象时,系统首先自动创建一个基类对象,也就是说,在调用派生类构造函数创建派生类对象之前,系统首先调用基类的构造函数创建基类对象。当派生类对象生命期结束时,首先调用派生类的析构函数,...
  • 如何从派生类函数调用父类函数

    千次阅读 2020-01-09 14:17:27
    如何使用C ++从派生类调用函数? 例如,我有一个名为parent的类,以及一个称为child的类,该类是从parent派生的。 每个类中都有一个print功能。 定义孩子的打印功能时,
  • 实际编程,往往不直接通过派生类对象来调用成员函数,而是通过一个指向派生类对象的指针(或引用)来调用成员函数。这面向对象编程非常常见。其好处是:通过这个基类指针或者引用来调用虚函数的时候,...
  • (2)一个派生类对象创建时不仅要调用派生类构造函数,而且要调用基类构造函数派生类中的数据成员在派生类中构造。 基类的数据成员在基类构造。 原因: A.构造函数不继承。 B.派生类的构造函数必须通过调用...
  • 我们都知道,C++编译器对于普通的类成员函数的编译,会将其编译成非成员函数,即普通全局函数,并且对函数名进行name-mangling,加入this指针作为该函数的第一参数,这个this指针的类型是本类型 即 class A { ...
  • {派生类中新增数据成员的初始化语句} 执行派生类构造函数的顺序是: (1)先调用基类的构造函数,对基类数据成员进行初始化 (2)调用子对象的构造函数,对子对象数据成员进行初始化 (3)最后执行派生类构造...
  • C++派生类函数调用基类的函数

    万次阅读 2014-07-17 15:48:05
    MFC的程序,我们经常会看到下面的程序片段,
  • 派生类的构造函数只负责对派生类新增的成员进行初始化,对所有从基类继承下来的成员,其初始化工作还是由基类的构造函数完成。 派生类的数据成员是由所有基类的数据成员派生类新增的数据成员共同组成的。如果派生...
  • 派生类对象地址赋值给 基类指针 和 派生类指针 后, 同名函数可能会发生 override 和 隐藏 情况. override:派生类函数与基类函数同名, 参数也相同, 且基类函数含有 virtual 关键字 隐藏: 指派生类的函数屏蔽了...
  • 派生类对自身基类的private成员没有访问权限,对基类对象的protected成员没有访问权限,对派生类对象的(基类之外)的private和protected成员具有访问权限。 由于C++基础不好,平时也不用它,导致今天才纠正一个...
  • A:继承与派生过程,基类的构造函数不能被继承,派生类中需要声明自己的构造函数。 B:声明构造函数时,只需要对本类新增成员进行初始化。至于基类继承过来的成员,应该调用基类的构造函数来完成 C:需要强调的是...
  • 近期网上搜寻了一下关于C++派生类构造函数调用问题,大部分博文给出的顺序是: 1、基类构造 2、成员构造 3、派生构造。 这个顺序严格来讲是错误的,对新手极具误导性!  依据侯捷翻译的Stanley B. Lippman...
  • /*假设基类函数被重载,当派生类覆盖基类的成员函数时,会隐藏到基类的其他的重载函数 * 注:应该尽量避免隐藏基类的成员函数 */ class Person { protected: //只能在派生类内部访问protected成员,外部不可访问 ...
  • 将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在成员函数中不能对的任何成员进行修改。 1.const对象可以调用非const成员函数吗? 2.非const对象...
  •  《Thinking in C++》,刘宗田等译,第261页:可以看出,构造在类层次的最根处开始,而每一层,首先调用基类构造函数,然后调用成员对象构造函数。  《C++ Primer Plus(第四版)中文版》,
  • 如果类A和类B是从同一个基类N派生的,且类D是类A和类B的多重继承派生类,要求程序通过类A和类B的构造函数调用基类N的构造函数,分别对类A和类B的数据成员a初始化。 #include<iostream> using namespace ...
  • 我们来看下面一段代码:  class B1  { public: B1(int i) {cout  };  class B2  { public: B2(int j)  {cout  };  class B3  { ... class C: public B2, public B1, publi
  • #include  using namespace std;...class A { protected: virtual void display (){cout "virtual void display ()"  } ; class B:public A { protected: B(){cout "B()"  ~B(){cout
  • 派生类构造函数调用顺序: 基类的构造函数(如果有多个基类,按照基类的声明顺序来构造,声明顺序也就是class C:冒号后面这个顺序);该派生类成员变量的声明顺序;该派生类自身的构造函数 派生类析构的顺序:...
  • 直接调用类成员函数地址

    千次阅读 2011-09-04 08:02:22
    摘要:介绍了如何取成员函数的地址以及调用该地址. ... C++成员函数的指针是个比较特殊的东西。对普通的函数指针来说,可以视为一个地址,需要的时候可以任意转换并直接调用。但对成员函数来说,常规类型

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 81,340
精华内容 32,536
关键字:

在派生类c中调用a的成员函数