C++类基础知识总结

来源:互联网 发布:知行理工app最新 编辑:程序博客网 时间:2024/05/19 01:30

对象指针被强转为void*后再delete,是不会调用对象的析构函数的。

1. 类的大小

空类大小为1 (因为需要一个占位符,否则创建对象时无法分配内存)

带有虚函数的类的大小要加一个虚函数指针的大小,32位下4

静态成员数据不属于类,所以类的大小不受虑静态成员数据影响

 

2.构造函数和析构函数

    2.1  可以显示调用构造函数和析构函数,其作用就和普通函数一样,并不创建和销毁对象。

   如:

   b.B::B();

   b.~B();

   如果对象生命周期是存在于栈上的。也就是说,如何管理,是系统完成而程序员不能控制的。所以,即使我们调用了析构,在对  象   生命周期结束后,系统仍然会再调用一次析构函数,将其在栈上销毁,实现真正的析构。(这时候如果显示调用析构函数和构造  函数的话,容易造成崩溃或内存泄露).

   如果是在堆上,则程序员可自己管理,重载new和delete,实现内存池。

   2.2 构造函数调用顺序

    类先调用父类的构造函数,再调用成员对象的构造函数,最后调用自身的构造函数。

    成员对象的构造函数调用顺序,和成员对象的声明顺序一致. 

   2.3 显示定义了虚析构函数则不能定义默认析构函数,否则编译出错

 

3.构造函数参数列表

    3.1不得不用参数列表初始化

  如果类中有一个对象成员,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如下,如果不适用初始化列表初始化m_ct,则School无法创建对象,编译报错.

class CT
{
public:
 CT(int x, int y, int iAge);
private:
 int m_x;
 int m_y;
 int m_iAge;
}; 

class School
{
public:
 School():m_ct(1, 20, 26)
 {

 }
 CT m_ct;
};

   3.2 对于较大的成员对象,提高效率

    这个地方还没弄的彻底明白,稍后继续

 

    拷贝构造函数和负值

   

#define MAXNAMELEN   24

class Complex
{
public:
 Complex();
 Complex(const Complex &cpl);
 Complex operator +(Complex &c2);
 Complex operator =(Complex &c2);
 ~Complex();
private:

 int x;
 int y;
 char *m_pszMyName;
};

Complex::Complex()
{   
 x = 0;    
 y = 0;    
 m_pszMyName = (char *)malloc(MAXNAMELEN);   
 memset(m_pszMyName, '\0', MAXNAMELEN);

Complex::Complex(const Complex &cpl)
{    
 x = cpl.x;  
 y = cpl.y;   
 m_pszMyName = (char *)malloc(MAXNAMELEN);   
 memset(m_pszMyName, '\0', MAXNAMELEN);   
 memcpy(m_pszMyName, cpl.m_pszMyName, MAXNAMELEN);

Complex::~Complex()
{    
 free(m_pszMyName);
 m_pszMyName = NULL;

Complex Complex::operator +(Complex &c2)
{   
 Complex c;
 c.x = x + c2.x; 
 c.y += y + c2.y; 
 return c;

Complex Complex::operator = (Complex &cp1)
{    
 Complex c;   
 c.m_pszMyName = (char *)malloc(MAXNAMELEN);  
 c.x = cp1.x; 
 c.y = cp1.y;   
 return c;
}

 

这里注意:

 Complex com1;
 Complex com2;
 com1 = com2;   //调用赋值重载和拷贝构造函数,因为return c. //如果将赋值重载函数定义为Complex& operator =(Complex &c2);

                            //则只调用赋值重载,不会调用拷贝构造了

 

如果 Complex com1;

          Complex com2 = com1; //这里是拷贝构造函数,而不是赋值,语义是用com1创建com2,和Complex com2(com1);是一样的

 

 

    派生类的构造函数

    派生类构造函数的一般形式为:

    派生类构造函数名(总参数列表) :  父类构造函数名(参数列表) //如果不调用父类构造函数,则使用默认构造函数

    {

    }

     //通常不希望使用默认构造函数

 

 

4. 与类相关的const 

    3.1 常对象

    常对象的所有数据成员的值不能被修改;

    在定义的时候使用构造函数初始化成员,如 const CT ct(1, 20, 26);

    常对象只能调用常成员函数,不能调用非常成员函数(编译器无法保证数据不被修改)

 

    3.2 常成员变量

     只能使用构造函数初始化列表来初始化常成员,如:

     CT::CT(int x, int y, int iAge) : m_iAge(iAge)
     {
             m_x = x;
             m_y = y; 
     }

   

    3.3 常成员函数  

    声明:<类型标志符>函数名(参数表)const

  (1const是函数类型的一部分,在实现部分也要带该关键字。

  (2const关键字可以用于对重载函数的区分,所以在实现的时候要带const关键字。

  (3常成员函数不能更新类的成员变量,但是可以调用成员变量;

            也不能调用该类中没有用const修饰的成员函数,只能常成员函数


5.this指针

memset(this, 0, sizeof(*this)),或者ZeroMemory() 本意是想对成员用0初始化,但是也会将虚函数表清0

如果一个类,有虚函数,当调用虚函数的时候,就会报空指针错误


6. 虚函数不能为内置函数.因为内联函数是不能在运行中动态确定其位置的。 即使虚函数在类的内部定义,
编译时,仍将其看作非内联的

 

 



 


0 0
原创粉丝点击