new 二维数组

在堆上声明一个数组 int main( ) { #if 0// 方式一: int** pArr = NULL; pArr = new int*[4]; for(int i = 0; i < 4; i++){ pArr[i] = new int[8]; } for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ pArr[i][j] = i * j; } } for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ if(j == 0) cout << endl; cout << pArr[i][j] << '\t'; } } // 删除 for(int i = 0; i < 4; ++i){ delete [] pArr[i]; } delete [] pArr; #endif // 方式二: cout << sizeof(int[5]) << endl; // 初始化 int(*pArr)[8] = new int[4][8]; memset(pArr, 0, sizeof(int[4][8])); // 或者 // int(*pArr)[8] = new int[4][8]{{0}}; cout << sizeof(int[4][8]) << endl; for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ pArr[i][j] = i * j; } } for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ cout << pArr[i][j] << '\t'; } cout << endl; } cout << endl; delete[] pArr; // 取地址 int arr[3][4]{{0}}; int(*p)[3][4] = &arr; cout << arr[2][3] << endl; cout << *p[2][3] << endl; return 0; } 输出:...

December 29, 2021 · 2 min · Rick Cui

类其它总结

1. this指针 this 指针是一个隐含于每一个非静态成员函数中的特殊指针,它指向调用该成员函数的对象的首地址 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用 this 指针 this 指针被隐含地声明为: ClassName *const this,这意味着不能给 this 指针赋值 this 是个右值,所以不能取 this 的地址 2. delete this 类的成员函数中可以调用 delete this,但是在释放后,对象后续调用的方法不能再用到 this 指针 delete this 释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,此时其中的值是不确定的 delete 的本质是为将被释放的内存调用一个或多个析构函数,如果在类的析构函数中调用 delete this,会陷入无限递归,造成栈溢出 3. 一个空类class中有什么? 构造函数、拷贝构造函数、析构函数、赋值运算符重载、取地址操作符重载、被 const 修饰的取地址操作符重载 4. C++ 计算一个类的 sizeof 一个空的类 sizeof 返回 1,因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址 类内的普通成员函数不参与 sizeof 的统计,因为 sizeof 是针对实例的,而普通成员函数,是针对类体的 一个类如果含有虚函数,则这个类中有一个指向虚函数表的指针(虚函数指针),32位程序占4个字节,64位程序占8个字节 静态成员不影响类的大小,被编译器放在程序的数据段中 普通继承的类sizeof,会得到基类的大小加上派生类自身成员的大小 当存在虚拟继承时,派生类中会有一个指向虚基类表的指针。所以其大小应为普通继承的大小,再加上虚基类表的指针大小 5. 构造函数和析构函数能被继承吗? 不能。构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么 6. 构造函数能不能是虚函数? 不能。虚函数对应一个虚函数表,可是这个虚函数表存储在对象的内存空间的。问题就在于,如果构造函数是虚的,就需要通过 虚函数表来调用,可是对象还没有实例化,也就是内存空间还没有,就不会有虚函数表...

December 28, 2021 · 1 min · Rick Cui

构造函数重载与互调

构造函数可以互调,但不能在函数体内,只能通过初始化列表的形式 构造函数中不要写业务逻辑 析构函数中不要 delete this ,这会导致析构递归,最终导致栈溢出 class Test{ public: Test(int a, int b, int c){ _a = a; _b = b; _c = c; } // 正确 Test(int a, int b):Test(a, b, 100){ } /* // 错误 Test(int a, int b){ _a = a; _b = b; Test(a, b, 100); // 此处只是产生一个临时对象,马上又被释放掉了,没有任何意义 } */ int getA(){ return _a; } int getB(){ return _b; } int getC(){ return _c; } private: int _a; int _b; int _c; }; int main( ) { Test t1(10, 20); cout << t1....

December 28, 2021 · 1 min · Rick Cui

类的成员函数作为回调函数

思路是借助类的静态成员函数 方式一: class A{ public: A(int a){ m_a = a; } void print(){ cout << "m_a = " << m_a << endl; } void setCur(){ s_curA = this; } static void callback(){ s_curA->print(); } private: static A* s_curA; int m_a; }; A* A::s_curA = nullptr; typedef void (*FUN_S)(); void Handle(FUN_S call){ call(); } int main( ) { A a(10), b(20); a.setCur(); Handle(A::callback); b.setCur(); Handle(A::callback); return 0; } 方式二: class A{ public: A(int a){ m_a = a; } void print(){ cout << "m_a = " << m_a << endl; } static void callback(void *a){ ((A*)a)->print(); } private: int m_a; }; typedef void (*FUN)(void *); void Handle(void *a, FUN call){ call(a); } int main( ) { A a(10), b(20); Handle(&a, A::callback); Handle(&b, A::callback); return 0; } 输出:...

December 28, 2021 · 2 min · Rick Cui

类的兼容性原则

父类指针可以new子类对象,子类指针不可以new父类对象,但是可以接收强转的已经存在的父类指针 父类指针指向本类对象,调用的虚函数和普通函数都是自己的 将子类指针指向父类对象,虚函数执行的是父类的,也可以调用子类函数(这种操作是错误的,编译会报错,虽然可通过指针强转,但是不建议这样做,可能会导致未知错误) 父类指针指向子类对象,虚函数执行的是子类的,并且不能调用子类的函数 父类指针与子类指针之间赋值可以理解为指针所指内容的一种浅拷贝 Father *f = (Father*)Child * 子类的虚函数指针覆盖父类的,并且子类特有的函数指针不会拷贝过去 Child *c = (Child*)new Father父类的虚函数指针覆盖子类的,同时也有子类特有的函数指针 class A{ public: void printA(){ cout << "printA()" << endl; } virtual void print(){ cout << "A::print()" << endl; } }; class B:public A{ public: void printB(){ cout << "printB()" << endl; } virtual void print() override{ cout << "B::print() b = " << b << endl; } private: int b; }; int main( ) { // 1、指向自己的类对象(将父类对象赋值给父类指针) A *a = new A; // 1....

December 28, 2021 · 1 min · Rick Cui