c++学习之一
.const总结
.html
C++语言概述——C++常类型(const)
.html
#define f(x) x*x
i = f (4+4) / f (2+2); // 4 + 4 * 4 + 4 / 2 + 2 * 2 + 2 =28 -_-|||
int a[10] = {1, 2}; // 1 2 0 0 0 0 0 0 0 0
int b[3] = {1, 2, 3, 4, 5}; // 1 2 3
◆不在定义成员变量时赋值
◆类的接口部分(Interface)和实现部分(Implementation)分开时,仅在接口或实现部分的一处对成员函数的参数赋默认值。
◆const 数据成员可以通过带参数表的构造函数进行初始化。
◆const 成员函数不能更改类中的数据成员。
◆const 对象只能调用常成员函数,其数据成员不能被改变。
◆函数参数采用形如 const int& i 的带const修饰符的引用传递,可以保证代码的高效和参数不被更改。
引用类型不能直接赋值,如 int& a = 1; // ERROR
引用类型相当于对象的别名alias
◆引用作函数参数,函数体不改变参数值 func (int& i);
◆引用作函数返回值,使函数调用可出现在赋值左部,重载[]。 int& index (int i) {return a[i];}; index (2) = 50; // 实现 a[2] = 50, a[i]成为函数返回值的“别名”。
◆◆函数返回值为引用类型,一般return *this; 或return a[i];须注意构造深拷贝函数。
%u %d %o %x %e %c %s %p
/n /t /f /r
多看看指针运算,指针数组,常指针等。
类的实例化过程:(不确定的想法)
参考:.shtm
ClassA* pCa; // 在栈中分配空的类引用指针
pCa = new ClassA(); // 在堆中分配空间存放类的实例,类引用指针指向类的实例
ClassA Ca(); // 在栈中分配空的类引用,在堆中分配空间存放类的实例
拷贝构造函数
◆T& operator = (const T& t1); // 运算符重载实现转换拷贝
◆Tobj obj1 (obj2); // 或Tobj obj1 = obj2; 拷贝过程执行拷贝构造函数Tobj (Tobj& obj2); 未声明则默认浅拷贝,即对成员变量赋值,对成员指针变量赋地址(obj1与obj2地址相同,指向相同的堆空间,删除其一将产生指针悬挂);要进行深拷贝,须添加拷贝函数,分配指针成员变量的空间并赋值。
例如:
赋值运算符的重载(实现类型转换)
◆当拷贝构造函数已经定义时,以下均自动完成,无需定义运算符重载。
◆在类的实例化过程中,通过带params参数的构造函数完成从参数到类的类型转换,如Tobj obj1 = params; 这个大概不算重载?
◆在类中重载运算符 Tobj& operator = (int params); ,可实现如下转换拷贝,Tobj obj1; obj1 = params;
◆在类中重载运算符 Tobj& operator = ((const Tobj& objSrc); ,可实现如下转换拷贝,Tobj obj1; obj1 = obj2; 或 obj1 = Tobj (params); 后者产生临时对象。
转换运算符的重载
◆ operator T(); 不需要参数和返回值,返回类型为T, 如operator int () {return n;} 从T类到int的转换。
◆典型应用,String str1 = String(Tstr1); 或 str1 = Tstr1.String();
对象数组可用指针数组的方式实现,可完成构造初始化,且不产生临时对象。
Cclass *classpnt[3];
classpnt[0] = new Cclass (params);
见:静态成员.dsw
静态数据成员 static int staticMember;
◆为同类对象共享,只分配一次空间。
◆在类的实现部分进行空间分配、初始化。如 int Cgoods::totalweight = 0;
◆对其访问:1、类名引导Cclass :: staticMember;2、对象引导CclassSample.staticMember;
静态函数成员函数 static void funcName();
◆无this指针,不能直接访问类中非静态数据成员。◆访问同静态数据成员。◆可在对象建立之前操作静态数据成员。
◆一般定义为inline。◆在接口部分实现时不加static。
友元函数 friend Tcomplex add (Tcomplex& c1, Tcomplex& c2);
◆常用于函数操作多个类对象。授权非成员函数访问私有数据成员。如 复数运算
◆在接口部分定义如上,在实现部分 如 Tcomplex add (Tcomplex& c1, Tcomplex& c2) { // }; 使用 如 Tcomplex c3 = add (c1, c2);
◆通过对象访问所有成员。◆无this指针,不能直接访问数据成员。◆在函数实现时不加friend。
虚函数表
编译器为包含虚函数的类创建一个虚函数表(virtual table/ vtable),表中包含各指向类中各虚函数的指针。
创建对象的同时,创建一个p隐藏指针(v-pointer),通过该指针,找到vtable,再找到相应的虚函数的指针。
地址的隐式转换
如 int *p; p = Iint*) 0x00431c10; cout p + 1; // 不是0x00431c11 而是 0x00431c14! 在 p + 1 的过程中,完成隐式转换 p + sizeof
(int) = 0x00431c10 + 4 =0x00431c14
类做基类时(抽象类),需定义虚析构函数 virtual ~Tclass () {}
类做基类,且要避免实例化时,定义纯析构函数 virtual ~Tclass () = 0;
静态联编与动态联编
◆静态联编:编译器根据实参确定同名函数的选择。速度快,不灵活。
◆动态联编:程序运行时调用同名函数。
条件:1、继承并创建子类;2、基类有虚函数(同参、同返回值,非静态,不能是构造函数);3、通过基类的对象指针(指向派生对象
)或引用(引用派生对象)来访问虚函数。
虚函数的动态联发生在:(不确定的想法)
◆指向派生实例的基类指针 Base* pBase = new Deprived ();
◆指向派生实例的基类引用 void func (Base& DeprivedExm);
◆其余情况不发生动态联编。
例如:
class Base {
int _size, *data;
public:
Base (int s) { _size = s; data = new int[s]; }
~Base () { delete[] data; } //◆1◆
void Pnt1 () {} // 1
vitual void Pnt2 () {} // 2 //◆2◆
};
class Deprived {
public:
Deprived (int size) : Base (size) {}
~Deprived () {}
void Pnt1 () {} // 3
void Pnt2 () {} // 4
};
void Pnt (Base&);
int main (void) {
Base base (5); // 调用Base构造
Deprived deprived (5); // 调用Base - Deprived构造
Base *pBase = new Deprived (5); // 调用Base - Deprived构造
base.Pnt1 (); // 1
deprived.Pnt1 (); // 3
pBase.Pnt1 (); // 1
base.Pnt2 (); // 1
deprived.Pnt2 (); // 3
pBase.Pnt2 (); // 4 此处发生动态联编 // 指向派生实例的基类指针
Pnt (deprived); // 1 4 此处发生动态联编
delete pBase; // 析构:~Base ◆ 不调用 ~Deprived ###
// 析构:deprived.~Deprived - deprived.~Base
// 析构:base.~Deprived - base.~Base
return 0;
}
void Pnt (Base& DeprivedExm) { // 指向派生实例的基类引用
DeprivedExm.Pnt1 ();
DeprivedExm.Pnt2 ();
}
◆1◆改成 vitual ~Base () { delete[] data; } ,### 处调用 析构:~Deprived - ~Base
◆2◆改成 vitual void Pnt2 () = 0; Base成抽象类,⑴ ### 处调用 析构:~Base ;⑵ Base base (5);出错,抽象类不能实例化!;⑶
其析构虚化时 vitual ~Base () { delete[] data; } , ### 处调用 析构:~Deprived - ~Base
STL基础学习:
.aspx
更多推荐
c++学习之一
发布评论