对象、多态和空类的大小

什么是对象

  类就是拥有相等功能和相同的属性的对象的集合 -- 抽象的

  对象就是类的实例 -- 具体

  举个例子:

  

class A
{
    /*
    这里定义一些成员数据和一些操作,但是并没有指定使用这些数据和操作的“人”(实例或对象),所以说类是抽象的
    */
}

//这里指明了类A的使用对象是obj,是具体的
A obj;

 

面向对象的三大特征: 

封装:找到变化并且把它封装起来,你就可以在不影响其它部分的情况下修改或扩展被封装的变化部分,这是所有设计模式的基础,就是封装变化,

因此封装的作用,就解决了程序的可扩展性。 

 

继承:子类继承父类,可以继承父类的方法及属性,实现了多态以及代码的重用,因此也解决了系统的重用性和扩展性,但是继承破坏了封装,

因为他是对子类开放的,修改父类会导致所有子类的改变,因此继承一定程度上又破坏了系统的可扩展性,所以继承需要慎用,

只有明确的IS-A关系才能使用,同时继承在在程序开发过程中重构得到的,而不是程序设计之初就使用继承,很多面向对象开发者滥用继承,

结果造成后期的代码解决不了需求的变化了。因此优先使用组合,而不是继承,是面向对象开发中一个重要的经验。 

 

多态:接口的多种不同的实现方式即为多态。接口是对行为的抽象,刚才在封装提到,找到变化部分并封装起来,但是封装起来后,怎么适应接下来的变化?

这正是接口的作用,接口的主要目的是为不相关的类提供通用的处理服务,我们可以想象一下。比如鸟会飞,但是超人也会飞,通过飞这个接口,

我们可以让鸟和超人,都实现这个接口,这就实现了系统的可维护性,可扩展性。 

 

 C++多态的实现

1、多态分为静态多态(函数重载和泛型编程)和动态多态(虚函数);

2、静态多态和动态多态的实际区别就是函数地址是早绑定还是晚绑定。如果函数调用时在编译期间就可以确定函数的调用地址并产生代码,就是静态的,也就是说地址是早绑定的(函数重载和泛型编程)。

而如果函数调用地址不能在编译期间确定,需要在运行时才能确定,这就属于晚绑定(通过虚函数实现);

3、C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时基类指针或引用将会根据对象的实际类型来调用相应的函数。

如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数

 

 

 

 

类的大小

 

1、C++标准规定类的大小不为0,空类的大小为1,当类不包含虚函数和非静态数据成员时,其对象大小也为1。

当类里面含有空的构造函数和虚析构函数的时候,类的到小也为1-->虚析构函数的内存大小也为1

#include<iostream>
using namespace std;
class ClassA
{};
class ClassB
{
    ClassB()
    {

    }
};
class ClassC
{
    ~ClassC()
    {

    }
};
class ClassD
{
    ClassD()
    {

    }
    ~ClassD()
    {

    }
};
int main()
{
    //类大小
    cout << sizeof(ClassA) << endl;//1
    cout << sizeof(ClassB) << endl;//1
    cout << sizeof(ClassC) << endl;//1
    cout << sizeof(ClassD) << endl;//1
    system("pause");
}
View Code

 

2、如果在类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针指向虚函数表VTable,在32位机器上,一个对象会增加4个字节来存储此指针,它是实现面向对象中多态的关键。而虚函数本身和其他成员函数一样,是不占用对象的空间的。 

#include<iostream>
using namespace std;
class ClassA
{
    virtual void GetNum();
};
class ClassB
{
    virtual void GetNum1();
    virtual void GetNum2();
};
int main()
{
    //类大小
    cout << sizeof(ClassA) << endl;//  4或8,也就是一个指针的大小
    cout << sizeof(ClassB) << endl;//  4或8,不管有几个虚函数,都和一个虚函数大小一样
    system("pause");
}
View Code

 

3、如果类里面包含静态成员数据,那么静态成员数据不占类内内存

#include<iostream>
using namespace std;
class ClassA
{
private:
    int a;
};
class ClassB
{
private:
    int a;
    static int b;
};
int main()
{
    static int b=0;
    //类大小
    cout << sizeof(ClassA) << endl;//  4
    cout << sizeof(ClassB) << endl;//  4
    system("pause");
}

 

 

 

 

 

我们来看下面一个例子:

posted @ 2020-04-21 17:37  知道了呀~  阅读(453)  评论(0编辑  收藏  举报