Thinking in C++【继承和组合】

1.继承语法

在类的左括号的前面,加一个冒号和基类的名字,这样,将会自动地得到基类中的所用数据成员和成员函数。

  • Y对X进行了继承,这意味着Y将包含X中的所有数据成员和成员函数。即,Y的大小是X大小的两倍。Y依然不能直接访问X的私有成员,但X的私有成员仍然占有存储空间。
  • 如果子类Y没有重写X的函数,如read(),那么调用的是父类X这个函数。
class X {
    
    
	int i;
public:
	X() {
    
    i = 0;}
	void set(int ii) {
    
     i = ii;}
	int read() const {
    
     return i; }
	int permute() {
    
    return i = i * 47;}
};

class Y : public X {
    
    
	int i;
public:
	Y() {
    
     i = 0; }
	int change() {
    
    
		i = permute();
		return i;
	}
	void set(int ii) {
    
    
	 	i = ii;
	 	X::set(ii);
	}
};

int main() {
    
    
    cout << "Sizeof(X) = " << sizeof(X) << endl;
    cout << "Sizeof(Y) = " << sizeof(Y) << endl;
    Y D;
    int temp1 = D.change();  //41
    int temp2 = D.read();  //0   
    int temp3 = D.permute(); //41*41
    cout << temp1 << '\n' << temp2 << '\n'  << temp3  << '\n'  <<endl;
    D.set(1);
}
  • C++基类中所有的成员都是被预设为私有的,若不添加public,则基类的所有公有成员将在派生类中变为私有。
  • Y继承X,如果Y没有重写X的公有成员函数,则Y里的同名函数实现方式与基类相同。

2.名字隐藏

  • 子类继承父类,并对它的成员函数重新进行定义:
    1)重定义: 在派生类中明确地定义操作和返回类型;
    2)重写: 如果基类的成员函数是虚函数
  • 任何时候重新定义了基类中的一个重载函数,在新类之中所有其他的版本则会被自动地隐藏起来了
class Base {
    
    
public:
    int f() const{
    
    
        cout << "Base::f()\n" << endl;
        return 1;
    }
    int f(string) const {
    
     return 1; }
    void g() {
    
    }
};

class Derived1 : public Base {
    
    
public:
    //重定义了g()
    void g() const {
    
    }
    //Base()的两个函数f()都可以使用
};

class Derived2 : public Base {
    
    
public:
    //Derived2重定义了函数f()的一个版本,而对另一个版本没有进行重定义,因此第2个重载形式不可以使用
    int f() const {
    
    
        cout << "Derived2:f()\n" << endl;
        return 2;
    }
    //int f(string) const 被隐藏起来了
};


class Derived3 : public Base {
    
    
public:
    //通过改变返回类型隐藏了基类中的两个函数版本
    void f() const {
    
     cout << "Derived3::f()\n"; }
};

class Derived4 : public Base {
    
    
public:
    //通过改变参数列表同样
    int f(int) const {
    
    
        cout << "Derived4::f()\n" <<endl;
        return 4;
    }
};
int main(){
    
    
    string s("hello");
    Derived1 d1;
    int x = d1.f();
    d1.f(s);
    Derived2 d2;
    x = d2.f();
    //!d2.f(s);             // string version hidden
    Derived3 d3;
    //! x = d3.f();         // return int version hidden
    Derived4 d4;
    //! x = d4.f();        //f() version hidden
    x = d4.f(1);
    return 0;
}

3.对私有继承成员公有化

当私有继承时,基类的所有public成员都变成了private。如果希望它们中的任何一个是可视的,只要派生类的public部分声明它们的名字即可:


class Pet {
    
    
public:
    char eat() const {
    
     return 'a'; }
    int speak() const {
    
     return 2; }
    float sleep() const {
    
     return 3.0; }
    float sleep(int) const {
    
     return 4.0; }
};

class Goldfish : Pet {
    
     //private inheritance
public:
    using Pet:: eat;
    using Pet::sleep;
};

int main(){
    
    
    Goldfish bob;
    bob.eat();
    bob.sleep(1);
    return 0;
}

4.protected

  • //! void set(int ii) { j = ii; } //若无重定义,则void change(int x) { set(x); }调用的是Base::set();
class Base {
    
    
    int i;
protected:
    int read() const {
    
     return i; }
    void set(int ii) {
    
     i = ii; }
public:
    Base(int ii = 0) : i(ii) {
    
    }
    int value(int m) const {
    
     return m*i; }
};

class Derived : public Base {
    
    
    int j;
public:
    //! void set(int ii) { j = ii; }        //若无重定义,则void change(int x) { set(x); }调用的是Base::set();
    Derived(int jj = 0) : j(jj) {
    
    }
    void change(int x) {
    
     set(x); }
    int getJ() {
    
     return j; }
};

int main() {
    
    
    Derived d;
    d.change(10);
    int a = d.getJ();
    cout <<  a << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43118572/article/details/112498350
今日推荐