c++ 继承

继承的概念

总结:继承的本质就是复用,集成的作用就是减少重复代码

 例如有羊,猫,狗三个动物.每个动物都有性别,年龄等属性.都有行走,睡觉等方法.我们可以为每个动物写一个类,如下:

class sheep
{
public:
	void work()
	{

	}
	void sleep()
	{

	}
private:
	int _age;
	int _sex;
};
class dog
{
public:
	void work()
	{

	}
	void sleep()
	{

	}
private:
	int _age;
	int _sex;
};

class cat
{
public:
	void work()
	{

	}
	void sleep()
	{

	}
private:
	int _age;
	int _sex;
};

我们发现其中大部分东西都是重复的,我们可以将其公用的属性和方法封装到一个类里面,然后其他的类都复用这个类即可:

class Animal
{
public:
	void work()
	{

	}
	void sleep()
	{

	}
private:
	int _age;
	int _sex;
};
class sheep: public Animal{};
class dog: public Animal{};
class cat: public Animal{};

继承的三种方式

继承有三种继承方式:public,protect,private.

通过观察下面代码我们可以总结规律:

sleep() 方法在 Animal 类中是 protected 的,这意味着它只能在 Animal 类本身、Animal 的派生类(如 sheepdogcat)内部,以及这些派生类的友元函数中被访问。在派生类的外部(如 main 函数中),sleep() 是不可见的,无论是通过 sheepdog 还是 cat 的实例。

此外,尝试直接访问 _age 也是错误的,因为 _age 是 Animal 类的私有成员,即使 sheep 是 Animal 的公共派生类,它也不能直接访问基类的私有成员。

#include<iostream>  
using namespace std;

class Animal
{
public:
    void work()
    {
        cout << "Animal is working" << endl;
    }
protected:
    void sleep()
    {
        cout << "Animal is sleeping" << endl;
    }
private:
    int _age;
    int _sex;
};

class sheep : public Animal
{
public:
    sheep() {
        work();
    }

    void wakeUpAndWork() {
        sleep();
        work();
    }
};

class dog : protected Animal
{
public:
    dog()
    {
        work();
        sleep();
    }

    // 如果需要,可以在这里添加一个函数来间接调用sleep(),但这在main中仍然不可见  
    // void dogSleep() { sleep(); }  
};

class cat : private Animal
{
public:
    cat()
    {
        work();
        sleep();
    }

    // 注意:由于private继承,这里不能添加任何公开的成员函数来调用sleep()或work(),  
    // 除非它们有其他的用途(比如设置或获取私有数据)  
};

int main()
{
    sheep mySheep;
    //mySheep.sleep();   // 这行是错误的,因为sleep()在基类中是protected权限,因此在sheep类外部不可见  
    //mySheep._age = 10; // 错误:_age在基类中是私有的,不能直接访问  
    mySheep.wakeUpAndWork();


    dog myDog;
    //myDog._age = 10; // 错误:_age在基类中是私有的,不能直接访问  
    // myDog.sleep(); // 这行是错误的,因为sleep()在基类中是protected权限,因此在dog类外部不可见  


    cat myCat;
    //myCat._age = 10; // 错误:_age在基类中是私有的,不能直接访问  
    //myCat.sleep();   // 这行是错误的,因为sleep()在基类中是protected权限,因此在cat类外部不可见  
    return 0;
}

子类所占字节大小

如下,代码运行之后会输出的字节大小是多少:

class Animal
{
public:
    void work()
    {
        cout << "Animal is working" << endl;
    }
protected:
    void sleep()
    {
        cout << "Animal is sleeping" << endl;
    }
private:
    int _age;
    int _sex;
};

class sheep : public Animal
{
public:
private:
    int color;
};
int main()
{
    cout << sizeof(sheep) << endl;
    return 0;
}

首先打开VS开发人员命令提示符(Developer Command Prompt ..),然后输入当前目录所在的盘符.

然后输出下面命令:

cd 当前目录绝对路径
dir

 就会有下面的显示:

然后我们输入下面命令:

cl /d1 reportSingleClassLayout要查的类名 "filename.cpp"

就会弹出下面的布局:

我们可以观察到子类sheep的字节大小为12,其中有2个继承与父类Animal的成员变量占了8字节,然后自己的一个成员变量占了4字节.

继承的构造析构顺序

如下代码:

#include<iostream>  
using namespace std;

class Animal
{
public:
    Animal()
    {
        cout << "父类构造函数" << endl;
    }
    ~Animal()
    {
        cout << "父类析构函数" << endl;
    }    
    void work()
    {
        cout << "Animal is working" << endl;
    }
protected:
    void sleep()
    {
        cout << "Animal is sleeping" << endl;
    }
private:
    int _age;
    int _sex;
};
class sheep : public Animal
{
public:
    sheep()
    {
        cout << "子类构造函数" << endl;
    }
    ~sheep()
    {
        cout << "子类析构函数" << endl;
    }
};

int main()
{
    sheep s;
    return 0;
}

通过运行结果,我们可以总结一条规则:

继承先调父类构造,再调子类构造.析构刚好相反.

多继承 

多继承就是一个子类继承多个父类.

如下所示,sheep类同时继承Animal,Pet,Mammals三个几类.同时,三个基类 都有共同的成员变量_age:


//动物类
class Animal
{
public:   
    void work()
    {
        cout << "Animal is working" << endl;
    }
protected:
    void sleep()
    {
        cout << "Animal is sleeping" << endl;
    }

    int _age;
    int _sex;
};

//宠物类
class Pet
{
public:
   
    int _age;
};

//哺乳动物类
class Mammals
{
public:
    int _age;
};
class sheep : public Animal,public Pet,public Mammals
{
};

 那我子类对象想调用_age就要通过指定作用域的方式去指定调用哪个父类下的_age:

int main()
{
    sheep s;
    s.Pet::_age = 10;
    return 0;
}

 

同名成员的处理

如下所示,子类sheep和父类Animal都有成员变量_age,其中父类的_age值为10,子类的_age值为20.此时通过子类对象调用_age,会输出10还是20呢?


//动物类
class Animal
{
public:   
    Animal()
    {
        _age = 10;
    }
    void work()
    {
        cout << "Animal is working" << endl;
    }
    void sleep()
    {
        cout << "Animal is sleeping" << endl;
    }

    int _age;
    int _sex;
};

class sheep : public Animal
{
public:
    sheep()
    {
        _age = 20;
    }
    int _age;
};

int main()
{
    sheep s;
    cout << s._age << endl;
    return 0;
}

答案是20:

规则如下:

int main()
{
    sheep s;
    cout << s.Animal::_age << endl;
    return 0;
}

同名静态成员的处理

首先要知道什么是静态成员.所谓的静态成员有三个特点:

静态成员变量的特性:

1.所有的静态对象共享一份数据

2.类内声明,类外定义

3.编译阶段分配内存

静态成员函数的特性:

1.只能访问静态的成员变量,不能访问非静态的成员变量

2.所有的对象共享同一份函数实例

静态成员调用规则

 静态同名成语的调用规则和非静态同名成员的调用规则一样:

 有如下两个类:

class Base
{
public:
	static int _a;
};
int Base::_a = 100;
class Son: public Base
{
public:
	static int _a;
};
int Son::_a=200;

 我们如果不指定作用域就默认调用子类:

int main()
{
	Son s;
	cout << s._a << endl;
	return  0;
}

指定了父类才会调父类:

int main()
{
	Son s;
	cout << s.Base::_a << endl;
	return  0;
}int main()
{
	Son s;
	cout << s.Base::_a << endl;
	return  0;
}

但是静态成员调用和非静态成员有一点区别,静态成员调用有2种方式:

1.通过对象调用

2.通过类名调用

通过类名的方式调同名静态变量

调子类的_age:

int main()
{
	Son s;
	cout << Son::_a << endl;
	return  0;
}

调父类的_age:

int main()
{
	Son s;
	cout << Base::_a << endl;
	return  0;
}

如果我想通过子类去调父类的_age呢:

int main()
{
	Son s;
	cout <<Son::Base::_a << endl;
	return  0;
}

调用同名静态成员函数

class Base
{
public:
	static void test();
	
	static int _a;
};
int Base::_a = 100;
void Base::test()
{
	cout << "1" << endl;
}


class Son: public Base
{
public:
	static void test();
	static int _a;
};
int Son::_a=200;
void Son::test()
{
	cout << "2" << endl;
}

 还是和上面一样,没限定符默认调用子类的,有限定符指定父类调父类的:

int main()
{
	Son s;
	s.test();
	return  0;
}

int main()
{
	Son s;
	s.Base::test();
	return  0;
}

通过类名的方式调用同名静态成员函数

int main()
{
	Son s;
	Son::test();
	return  0;
}

int main()
{
	Son s;
	Base::test();
	return  0;
}

菱形继承的案列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙鹏宇.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值