目录
初始化列表
特点
一种便捷的初始化成员变量的方式
只能用在构造函数中
初始化顺序只跟成员变量的声明顺序有关
一、下面的2种写法是等价的
struct Person{
int _age;
int _height;
Person(int age,int height){
this->_age = age;
this->_height = height;
cout<<"this->age is "<<this->_age<<endl;
cout<<"this->height is "<<this->_height<<endl;
}
};
初始化列表只能在构造函数中
struct Person{
int _age;
int _height;
Person(int age,int height):_age(age),_height(height){
cout<<"this->age is "<<this->_age<<endl;
cout<<"this->height is "<<this->_height<<endl;
}
};
二、构造函数的互相调用
注意:下面的写法是错误的,初始化的是一个临时对象
struct Person{
int _age;
int _height;
Person(){
cout<<"this is11 "<<this<<endl;
//初始化的是一个临时对象
Person(0,0);
}
Person(int age,int height):_age(age),_height(height){
cout<<"this is "<<this<<endl;
cout<<"this->age is "<<this->_age<<endl;
cout<<"this->height is "<<this->_height<<endl;
}
};
struct Person{
int _age;
int _height;
//构造函数的调用
Person():Person(0,0){ }
//初始化列表的使用
Person(int age,int height):_age(age),_height(height){ }
};
三、初始化列表与默认参数配合使用
struct Person{
int _age;
int _height;
// Person(){}
// Person(int age):Person(age,0){}
Person(int age = 0,int height= 0):_age(age),_height(height){
}
};
如果函数声明和实现是分离的
初始化列表只能写在函数的实现中
默认参数只能写在函数的声明中
struct Person{
int _age;
int _height;
// 默认参数只能写在函数的声明中
Person(int age = 0,int height=0);
};
// 构造函数的初始化列表只能写在实现中
Person::Person(int age,int height):_age(age),_height(height){
}
父类的构造函数
子类的构造函数默认会调用父类的无参构造函数
如果子类的构造函数显式地调用了父类的有参构造函数,就不会再去默认调用父类的无参构造函数
如果父类缺少无参构造函数,子类的构造函数必须显式调用父类的有参构造函数
class Animal{
int _age;
public:
int getAge(){
return _age;
}
Animal(){
cout<<"Animal"<<endl;
}
Animal(int age):_age(age){
cout<<" Animal(int age)"<<endl;
}
~Animal(){
cout<<"~Animal()"<<endl;
}
};
class Cat:public Animal{
int _life;
public:
Cat(int age=0,int life=0):Animal(age),_life(life){
//父类的构造函数相当于在此调用
cout<<" Cat(int age=0,int life=0)"<<endl;
}
~Cat(){
cout<<"~Cat()"<<endl;
//父类的析构函数相当于在此调用
}
};
void inheritUsing(){
Cat c;
}
构造函数与析构函数的调用顺序
Animal(int age)
Cat(int age=0,int life=0)
~Cat()
~Animal()
父类指针与子类指针
父类指针可以指向子类对象,是安全的,开发中经常用到(继承方式必须是public)
子类指针指向父类对象是不安全的
子类指针访问的范围会超出父类对象,会出现内存非法访问
void fatherAndSubClassUsing(){
Animal * an = new Animal();
//父类指针可以指向子类对象
Animal *an1 = new Cat();
//反之不可以
//Cat * ca = new Animal();
}
多态
默认情况下,编译器只会根据指针类型调用对应的函数,不存在多态
多态是面向对象非常重要的一个特性
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
在运行时,可以识别出真正的对象类型,调用对应子类中的函数
多态的要素
子类重写父类的成员函数(override)
父类指针指向子类对象
利用父类指针调用重写的成员函数
class Transport{
public:
// void run(){
// cout<<"Transport run"<<endl;
// };
//
// void stop(){
// cout<<"Transport stop"<<endl;
// };
/**
virtual虚函数
没有virtual修饰,子类不会调用重写的方法,而是会调用父类方法
需要有virtual修饰,子类重写后就会调用子类的方法
*/
virtual void run(){
cout<<"Transport run"<<endl;
};
virtual void stop(){
cout<<"Transport stop"<<endl;
};
};
class Truck:public Transport{
public:
void run(){
cout<<"Truck run"<<endl;
};
void stop(){
cout<<"Truck stop"<<endl;
};
};
class Car:public Transport{
public:
void run(){
cout<<"Car run"<<endl;
};
void stop(){
cout<<"Car stop"<<endl;
};
};
void paoAndTing(Transport * tran){
tran->run();
tran->stop();
}
void nineDayFunc(){
Transport * tran = new Transport();
Truck * truc = new Truck();
Car * ca = new Car();
//没有虚函数调用以左侧为准,有虚函数调用以右侧为准
paoAndTing(truc);
paoAndTing(ca);
}
行者常至,为者常成!