一,重载,重写,隐藏的区别
1,重载与重写
作用域不同:重写存在于继承体系下,也就是两个类中的两个函数,
重载存在于一个类中,也就是一个类中的两个函数。
参数列表不同:重写要求两个函数的参数列表完全相同,(协变和虚析构函数例外),且需要virtual修饰。
重载要求两个函数参数必须有不同之处。
2,隐藏与重写和重载的区别:
作用空间 :和重写一样,在继承体系下,也就是两个类中的两个函数。
参数列表:当没有virtual修饰时,参数列表可以相同,也可以不同,只需要函数名相同,就是隐藏。
当有virtual修饰时,参数列表相同就是重写,参数列表不同就是隐藏。
总结:重载是静态绑定的,隐藏是动态绑定的,虽然两者都实现了多态,但是有本质的区别。
二,虚函数和纯虚函数的区别
1,含有纯虚函数的类被称为抽象类,抽象类无法实例化对象,必须在派生类张对其进行重写才能使用。
也就是说,纯虚函数是为派生类服务的。
含有虚函数的类可以直接实例化对象,可以在派生类中对虚函数重写,也可以不重写。
三,简述C++三大特性
1,封装:
定义:将同一事物的特性抽象出来,放到一个类中,并用访问限定符进行修饰,将部分代码模块隐藏。
对外仅提供接口和方法。提高代码的安全性
2, 继承:
基类派生出派生类,派生类继承基类 ,的代码模块(包括数据和函数),实现代码的复用,
将类与类之间联系起来,是实现多态的基础。
3,多态:
定义:通过在基类中定义虚函数,在派生类中重写虚函数,通过基类的指针或者引用指向派生类对象。
由于基类指针指向的类的类型不一样,那么就会调用不同的函数。
调用实现接口的高度统一,简而言之就是,调用相同的接口,表现不同的结果。接口复用
四,什么成员函数不能被声明为虚函数
1,只有类的成员函数才能被声明为虚函数
2,静态成员函数不能被声明为虚函数
静态成员函数是属于类中的,依赖类而存在,虚函数必须要知道具体的对象类型才能确定调用哪一个,依赖对象而存在。
两者的依赖不同,终归是不能合二为一的。
3,构造函数不能被声明为虚函数
构造函数完成对象的初始化,也包括虚函数表的初始化。
虚函数的调用需要访问虚表,两者相互矛盾。
这两个事件在不同的时间点发生,不能合二为一的。
4,析构函数可以是虚函数,并且尽可能声明为虚函数
class Base
{
public:
Base()
{
cout << "Bulid a new Base" << endl;
}
~Base()
{
cout << "Delete something in Base" << endl;
}
};
class Device :public Base
{
public:
Device()
{
cout << "Build a new Device" << endl;
}
~Device()
{
cout << "Delete something in Device" << endl;
}
};
int main()
{
Base* p = new Device;
delete p;
return 0;
}
class Base
{
public:
Base()
{
cout << "Bulid a new Base" << endl;
}
virtual~Base()
{
cout << "Delete something in Base" << endl;
}
};
class Device :public Base
{
public:
Device()
{
cout << "Build a new Device" << endl;
}
~Device()
{
cout << "Delete something in Device" << endl;
}
};
int main()
{
Base* p = new Device;
delete p;
return 0;
}
对比发现:
在继承体系下,基类析构函数不是虚函数时,不会自动调用派生类析构函数,可能会造成内存泄漏。
也就是说,非虚析构函数时,编译器只会去看p的类型,显然是基类类型,所以直接调基类析构函数。
基类析构函数是虚函数时,会自动调用派生类的析构函数。
虚析构函数时,编译器只会去看p的对象,显然是派生类,所以先调派生类析构,再调基类析构。
5,内联函数不能被声明 为虚函数
内联函数会在编译时在函数调用的地方展开,所以不具有函数指针,但是虚函数时通过函数指针调用的。
6,友元函数不能是虚函数
友元函数不是类的成员函数。
五,那些函数不能被继承
1,构造函数
2,析构函数
3,拷贝构造函数