c++ day2

操作符重载
内置数据的表达式的运算符是不能进行重载的,比如(int)
1.+
类的成员函数做重载的时候,左边的对象隐式绑定了this指针上。(一元)
Person operator+(Person &p)
{
Person tmp;
tmp.bookname=this->bookname+p.bookname;
tmp.booknum=this->booknum+p.booknum;
return tmp;
}

或者在全局函数做重载,但是需要多加一个形参(二元)
Person operator+(Person &a,Person &b)
第一个形参是左边a的,然后是+,然后是第二个形参b ======>>> a+b
操作符函数可以重载。
Person wang(“wang”,12);
Person li(“li”,10);
Person total=wang+li;//等价于total=wang.operator+(li);
2.<<
不可以使用内成员函数做重载
ostream& operator<<(ostream& cout,Person& p)
{
cout<<p.bookname<<" has “<<p.booknum<<” books";
return cout;
}

3.++
区别前置++和后置++是后置++多一个占位符,后置++会比前置++多一笔开销,用于销毁局部的类成员
//前置++
Person& operator++()//返回引用 ++(++person)如果返回的不是引用,这一段输出之后person.num的值会少1
{
++this->booknum;
return *this;
}
//后置++
Person operator++(int)//返回值,如果把临时数据返回给引用,则会出错
{
Person tmp=*this;

++this->booknum;
return tmp;
}

4.=
类默认会定义一个Operator=操作符,会进行简单的值传递。
5.不要重载|| &&,因为这样会失去这两个操作符的短路特性。

6.继承方式
class Person
{
public: int c;
private:int b;
protected:int a;
};
6.1 公有继承
class Son:public Person
{
public: int c;
protected:int a;//

不可访问 int b 

};
6.2 保护继承(类外不可访问)
class Son2:protected Person
{
protected:
int c;
int a;
不可访问 int b
}
6.3私有继承
class Son3:private Person
{
private:
int c;
int a;
不可访问 int b
};

7.子类会继承父类的私有成员,只是被编译器隐藏了。
8.子类会继承父类的成员属性和成员函数,但是不会继承构造函数和析构函数,还有operator=
子类创建对象的时候,先调用父类的构造函数,再调用自己的构造函数
析构函数调用与构造函数相反
如果父类没有合适的默认构造函数,则子类可以利用初始化列表的方式显式调用父类的其他构造函数。
9.继承之后成员同名处理
成员先调用自己的类,如果想调用父类的成员,需要用作用域::来显式调用。
10.静态成员变量
class Base{
public:
static int a;在类内声明
}
无论是public还是private都可以在类外(不能在主函数里面,类似全局变量的定义方式)定义,定义方式为 int Base::a=2;不需要加static修饰符
静态成员在类是共享的,也就是说无论声明几个对象,他们的值都是一样的,值由最后一个初始化的对象决定。
访问可以通过.作用符号或者类名作用域Base::a,如果是private则不能通过这两种方式来访问。
普通成员函数可以访问静态成员变量

静态成员函数有权限的,也是在类中共享的,但是静态成员函数只能访问静态成员变量,不能访问普通成员变量。
静态成员变量和静态成员函数都可以被继承

11.多继承
class Base1
{
public:
int a;
};
class Base2
{
public:
int a;
};
class Son:public Base1,public Base2
{};
如果BASE1和base2都有一个成员叫做a,则调用 Son s;cout<<s.a;的时候会报错,这是多继承的二义性,解决方法就是利用类的作用域符号:: cout<<s.Base1::a<<endl;
12.菱形继承
class Animal
{
public:
int age;
};
class Sheep:(virtual)public Animal
{

};
class Tuo:(virtual)public Animal
{

};
class SheapTuo:public Sheap,public Animal
{
};
由于SheapTuo会继承来自Sheap Tuo各一份的age,但其实只需要一份就可以了,这样会造成资源浪费,同时也有二义性产生,解决方法就是在sheap tuo继承的时候加virtual,然后共享一份数据,此时sheapTuo s.age可以直接调用。

13.多态
多态的发生时机:当父类的引用或者指针指向子类对象
class Base
{
public:
virtual void speak()//发生多态需要父类,因为这个时候内部结构发生了改变,内部多了一个vfptr和vftable
vfptr指向vftable,里面存放着&Base::speak.子类会继承这两个东西,在构造过程中,会将vfptr指向自己的vftable而不是指向父类的vftable,如果发生了重写(返回值,参数个数,类型,顺序都和父类的虚函数一样),则会将&Base::speak改为&Son::speak.
{
cout<<“dad talk”<<endl;
}
};
class Son:public Base
{
public:
void speak()
{
cout<<“Son talk”<<endl;
}
};
void test(Base&s)
{
s.speak();
}

Son s;
s.speak();
Base *father=new Son;//发生多态,父类的指针指向子类对象
test(s);//发生多态 父类引用指向子类对象

14.抽象类 当父类有纯虚函数(只是提供一个接口,不需要具体的代码实现)virtual void func()=0;这个类就叫做抽象类,抽象类不能实例话对象,继承的子类必须把所有的纯虚函数实现。

15.当父类指针指向子类对象,如果子类对象有指针成员变量,因为无法调用子类的析构函数,所以会导致释放不干净。
父类的普通析构函数是无法调用子类的析构函数的,这时候只要将父类的析构函数变为虚析构函数就可以解决。
virtual ~类名()
纯虚析构函数virtual ~类名()=0 需要在类内申明,类外实现。(因为析构函数会调用,如果不给实现,会报错),如果出现纯虚析构函数,那么也算抽象类,不能够实例对象。

16类型转化安全性
Cat * cat=new Cat;
Animal * ani=(Animal) cat;
将子类强制转换成父类对象,是安全的。
Animal * ani=new Animal;
Cat * cat=(Cat*) ani;
将父类强制转换成子类对象,是不安全的。
Animal *ani=new Cat;
当发生多态,则总是安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值