c++继承体系种构造函数的调用顺序
C++继承体系中,初始化时构造函数的调用顺序如下
(1)任何虚拟基类的构造函数按照他们被继承的顺序构造
(2)任何非虚拟基类的构造函数按照他们被继承的顺序构造 +
(3)任何成员对象的函数按照他们声明的顺序构造
(4)类自己的构造函数
class A
{
public:
A ():m_iVal(0){
test();}
virtual void func() {
std::cout<<m_iVal<<‘ ’;}
void test(){
func();}
public:
int m_iVal;
};
class B : public A
{
public:
B(){
test();}
virtual void func()
{
++m_iVal;
std::cout<<m_iVal<<‘ ’;
}
};
int main(int argc ,char* argv[])
{
A*p = new B;
p->test();
return 0;
}
//B 继承自 A, 先 A 构造函数,输出 0 ,然后 B 构造函数, B 的 test 继承自 A ,然后找 func 函数找到 B 自己的,所以输出 1 ,然后 p->test() 再执行一次,输出 2
//在父类的构造函数中调用虚函数,还是会执行父类的构造函数,不会跑到子类中去,即使有vitual,因为此时父类都还没有构造完成,子类也就还没有构造。本题的输出顺序为:父类构造函数、子类构造函数、指向子类的父类指针(覆盖、多态),所以结果为012.
定义全局的类实例时,该类的构造函数比main先执行。并不是所有C++的程序是从main函数开始的
*(*(*((a+i)+j)+k)+l) = a[i][j][k][l]
由于打印字符串的首地址等于打印字符串
析构函数名与类名相同,只是在函数名前面加一个位取反符~,以区别于构造函数 。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载 。如果用户没有编写析构函数,编译器 自动生成一个缺省的析构函数(即使自定义了析构函数,编译器 也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。
&(引用)==>出现在变量声明语句中位于变量左边时,表示声明的是引用.
&(取地址运算符)==>在给变量赋初值时出现在等号右边或在执行语句中作为一元运算符出现时表示取对象的地址.
当一个类的某个函数被说明为virtual,则在该类的所有派生类中的同原型函数(都是虚函数)
#include<iostream> using namespace std; class MyClass { public: MyClass(int i = 0) { cout << i; } MyClass(const MyClass &x) { cout << 2; } MyClass &operator=(const MyClass &x) { cout << 3; return *this; } ~MyClass() { cout << 4; } }; int main() { //拷贝构造函数是一种特殊的构造函数,在A a=b;这种情况下调用它。 MyClass obj1(1), obj2(2);//构造函数 1 2 MyClass obj3=obj1;//拷贝构造函数 2 obj2=obj1;//复制函数 3 return 0;//三次析构函数 }//输出 1223444
含虚函数的类,除了基本的数据成员占用的内存,还有虚指针占据的内存(4个字节)。
且在内存中,虚指针的位置在首部,接下来才是普通成员变量的存储。
二维数组X按行顺序存储,其中每个元素占1个存储单元。若X[4][4]的存储地址为Oxf8b82140,X[9][9]的存
储地址为Oxf8b8221c,则X[7][7]的存储地址为(Oxf8b821c4 )。
参考: 添加链接描述
printf("%%%%")输出的为%%,而cout << “%%%%” << endl;输出却为%%%%,
两个%连在一起时,表示告诉编译器,此时的%不是一个格式控制符,而是一个普通字符。
是因为,printf()需要用%d、%c等转义字符串,这里的%与要输出的%冲突
在C++,哪一个可以做为对象继承之间的转换 ?
reinterpret_cast:一个指针转化为其他类型的指针时,不做类型检测,操作结果是一个指针指向另一个指针的值的二进制拷贝;
static_cast:允许执行隐式转换和相反的转换操作,父类转换为子类是强制转换Son *son=static_cast(father),而子类转换为父类就是隐式转换;
把子类的指针或引用转换成基类表示是安全的,但把基类指针或引用转换成子类指针或引用时,由于没有动态类型检查,所以,它是不安全的。
基类和子类之间的动态类型转换一般建议使用``dynamic_cast``。
dynamic_cast:用于对象的指针和引用,当用于多态类型转换时,允许隐式转换及相反的过程中,与static_cast的不同之处在于,在相反的转换过程中,dynamic_cast会检测操作的有效性,如果返回的不是被 请求的 有效完整对象,则返回null,反之返回这个有效的对象,如果是引用返回无效时则会抛出bad_cast异常;
对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;
对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。
const_cast:这个转换操作会操纵传递对象的const属性,或者设置或者移除该属性。
类模板的使用实际上是先将类模板实例化为模板类,再实例化成一个具体的类。
按类中声明变量的先后顺序来初始化,与初始化列表的顺序无关。
template<class T> class Foo{
T tVar;
public:
Foo(T t)