C++面向对象编程(下)第二周笔记 GeekBand

1.对象模型

C++对象模型中,non static数据成员被放置到对象内部,static数据成员,static and non static函数成员均被放到对象之外。
而对于虚函数的支持则分两步完成:
1.每一个class产生一堆指向虚函数的指针,放在表格之中。这个表格称之为虚函数表(virtual table,vtbl)。
2.每一个对象被添加了一个指针,指向相关的虚函数表vtbl。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的构造函数析构函数拷贝赋值运算符自动完成。

图 1 对象模型

例如图1中,由于A类中有虚函数,所以A类的对象中有自己的两个成员变量m_data1、m_date2和一个指向vtbl的指针(vptr)。B类是A类的子类,B类对象除了有父类对象所有成员和vptr外,还有自己的成员m_data3。这些对象占用内存的大小由它们的成员变量和vptr指针决定,在不同的编译环境下它们的内存大小会有所不同。

2.const

当类中成员函数的const和non-const版本同时存在时,const对象只会调用const版本,non-const对象只会调用non-const版本。
const对象和non-const对象都可以调用const成员函数;
non-const对象可以调用non-const成员函数而const对象则不可以。
例如以下程序:

#include <iostream>

class Foo
{
    public:
        Foo(int id) : id_(id) { }
        void print() const {
            std::cout<<"const print id:"<<id_<<std::endl;
        }
        void print() {
            std::cout<<"non-const print id:"<<id_<<std::endl;
        }
        void say() {
            std::cout<<"say id:"<<id_<<std::endl;
        }
        void tell() const {
            std::cout<<"tell id:"<<id_<<std::endl;
        }
    private:
        int id_;
};

int main()
{
    Foo a1 = Foo(6);
    const Foo a2 = Foo(5);
    a1.print();
    a2.print();
    a1.say();
    a1.tell();
    //a2.say();  //[Error] passing 'const Foo' as 'this' argument of 'void Foo::say()' discards qualifiers [-fpermissive]
    return 0;
}
图 2 测试结果

例中print函数同时有const和non-const版本,const对象和non-const对象都能调用对应的版本。而const对象调用non-const成员函数时编译会出错。

3.重载new和delete

C++中new,delete,new[],delete[]是可以重载的,这样可以在程序执行new或delete时另外地实现我们自己所想要的操作。
new,delete,new[],delete[]的重载分为全局重载和对特定类的重载。
例如:
全局重载

//global operator new/delete
void* myAlloc(size_t size){
    return malloc(size);
}

void myFree(void* ptr){
    return free(ptr);
}

inline void* operator new(size_t size){
    std::cout<<"global new() \n";
    return myAlloc(size);
}

inline void operator delete(void* ptr){
    std::cout<<"global delete() \n";
    return myFree(ptr);
}

对A类对象new,delete的重载

class A {

    int id;
public:
    A(int i):id(i){
        std::cout<<"A构造 \n";
    }
    ~A(){
        std::cout<<"A析构 \n";
    }   
    static void* operator new(size_t size);
    static void operator delete(void* pdead,size_t size);
};

//member operator new/delete
void* A::operator new(size_t size) {
    A* p = (A*)malloc(size);
    std::cout<<...........;
    return p;
}

void A::operator delete(void* pdead,size_t size) {
    std::cout<<...........;
    free(pdead);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容