C++面向对象

一般开发项目使用类中使用内联函数、

类内初始值,C++11才支持

默认构造函数:

1)白动调用 (在创建新对象时,自动调用)
2)构造函数的函数名,和类名相同
3)构造函数没有返回类型
4)可以有多个构造函数 (即函数重载形式)

构造函数的种类:
默认构造函数
自定义的构造函数
拷贝构造函数

自动合成的拷贝构造函数存在风险(是浅拷贝 ),当成员是指针的时候,指向同一个地址

//以下调用拷贝构造函数

Object h2 = h1;
Object h3(h1);

//自定义拷贝构造函数

Object(const Object &);

为了数据的安全,应该在定义接口的时候对象加上const,const对象只能调用const方法:

void showMsg(const Object &object){//使用引用,避免创建新的对象
    cout<<object.getName()<<endl;
}

void getName() const;//在方法后面加const,该方法中不允许成员变量的修改

什么时候调用拷贝构造函数: 

1.调用函数时,实参是对象,形参不是引用类型如果函数的形参是引用类型,就不会调用拷贝构造函数
2.函数的返回类型是类,而且不是引用类型
3.对象数组的初始化列表中,使用对象。


赋值构造函数

//以下情况调用赋值构造函数
Object h1,h2;
h1=h2;//已经存在了,再赋值
//构造自定义赋值构造函数

Object& operator = (const Object& other){
//防止对象给自己赋值,h1=h1
if(*this == other)
return *this;

name = other.name;
strcpy(addr, other.addr);

return *this;//返回引用,防止链式处理,h1=h2=h3
}

析构函数:对象销毁时,自动调用

~Object()//和类同名,前面加波浪号
{
    delete addr;//释放堆内存
}

类内静态static方法中,只能访问static数据成员(因为会产生歧义),也不能调用这个类的非static方法,静态数据成员不能使用this指针,静态类内成员变量定义好后,不再属于这个对象,而是一个单独的内存,静态对象不能在类内直接初始值(加了const的静态成员变量可以在类内初始化,但是不要在类内的类外初始化两次),要在外部进行初始化,初始化时不需要再带有static字样,使用类名可以直接访问public的静态成员变量,

//类的静态成员函数
static int count;

//&+对象为取地址符号

int Object::count = 0;//类外初始化

类文件的分离:

实际开发中,定义类的头文件 ,头文件包含类的定义,类内的方法只有声明,具体的实现在同类名的cpp文件中

const变量

const string c = "";//const变量在类内初始,C11支持

const变量还可以在构造函数自动赋值,const不可以在方法内进行初始化,const 对象不可以访问非const方法,因为非const方法会改变变量的值,方法后加了const关键字后,不能改变任何数据成员

void Object(int a, int b): c(b){
//把参数b赋值给c成员变量,初始化列表
}

组合与聚类,数据成员是对象的时候,生命周期和其拥有者一致,

//当数据成员是对象的时候也可以,对象是成员的非指针的时候是组合关系,
//指针为聚合关系,指针可以指定指向哪个对象

Computer::Computer(const char * cpuBrand, const char *cpuVersion, int hardDisk, int memory):cpu(cpuBrand, cpuVersion)
{
        this->hardDisk = hardDisk;
        this->memory = memory;
        //this->cpu = new cpu(cpuBrand, cpuVersion)
}

//以上cpu定义时为,也可以定义为指针,在构造函数中需要new一个对象,在析构函数中需要释放内存delete cpu

private:
        Cpu cpu;
        //Cpu *cpu;

//宏定义_FUNCTION_,用于打印当前函数的名称

cout<<__FUNCTION__<<endl;

聚合举例,当对象成员是指针,通过方法指向某个成员对象的时候,改对象消亡,指向的成员对象不消亡,当对某个对象只是使用关系,而不是完全占有的关系的时候

//需要包含的某个对象简单声明

class B;

class A{

public:
        void addB(B *b){//使用改方法指向某个对象,析构函数的时候不需要释放b,因为只是指向关系
            this->b = b;
        }

private:
        B *b;


}

 const变量不能直接赋值给引用类型存在风险,作为参数赋值的时候必须加const才能赋值

const Object object;

test(object);//会出错

void test(const Object &object){
        object.play();
}

继承与派生:

除了“析构函数”和“构造函数”,父类所有成员函数,以及数据成员都会被子类继承

继承方式有:

公有public继承,继承公共的类和变量,并且父类所有类型数据成员继承过来类型不变,子类不能直接访问private私有成员,需要把父类的成员private----->protected

私有private继承,父类所有类型的数据成员继承过来后都会变成私有的

protected继承,父类所有类型的数据成员继承过来后public会变成protected的


// 创建子类对象时,会调用构造函数!
// 会先调用父类的构造函数,用来初始化从父类继承的数据
// 再调用自己的构造函数,用来初始化自己定义的数据
没有体现父类的构造函数那就会自动调用父类的默认构造函数!!!

子类重载父类方法的时候,子类对象调用方法时,先在自己定义的方法中去寻找,如果有,就调用自己定义的方法如果找不到,就到父类的方法中去找,如果有,就调用父类的这个同名方法/如果还是找不到,就是发生错误!

Son::Son(const char *name, int age,const char *game) : Father(name,age){
    cout<<__FUNCTION__<<endl;
this->game = game;
}

派生类对象的内存分布:

父类的数据成员先分布,子类自己的数据成员后分布,函数不占内存

子类构造函数调用顺序:

1、静态数据成员对象构造函数

2、父类构造函数

3、普通数据成员对象构造函数

4、子类构造函数

子类的析构函数和子类构造函数调用相反

子类对象可以直接赋值给父类对象,父类对象不能赋值给子类对象,同理,父类的指针可以指向子类对象指针,但是子类对象指针不能指向父类对象指针,父类的引用可以指向子类对象

多重继承:继承多个父类,多继承构造函数的顺序和写的时候顺序一致,多重继承存在二义性(多个父类中存在同名函数或者属性)

1、需要在方法/属性前加上指定类名的限定

2、在子类中重新定义该方法,在方法中通过指定父类名来指定重名方法

检查类的内存分布:在C/C++ -> 命令行里添加:/d1 reportSingleClassLayoutXXX(XXX是类名),重新编译会在输出窗口的生成里看到对象布局和虚表布局。

虚继承:被共享的基类叫虚基类,可以很好的解决菱形继承

class B : virtual public A{

}

友元函数、友元类,在需要使用类的私有成员中声明函数/类,该类/函数可以访问该类的私有成员

使用成员函数在类中实现运算符重载

使用非成员函数在类中实现运算符重载(利用友元函数)

//需要在Cow中定义该友元函数
Pork operator+ (const Cow& cow1, const Cow& cow2){

    int tem = cow1.weight *2 + cow2.weight*3;
     return Pork(tem);

}
在调用时:首先查找有没有成员函数,再查找友元函数实现

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值