C++的拷贝构造函数和赋值运算符

使用原则:当对象中含有类型为指针的成员变量时,重载拷贝构造函数能够防止两对象共享同一成员指针的问题。

class Test
{
public:
    Test(void);             // 默认构造函数
    Test(const Test& t);    // 拷贝构造函数
    ~Test(void);            // 析构函数

private:
    char * name;            // 指针成员变量
};

Test::Test(void)
{
    name = NULL;
}

Test::~Test(void)
{
    delete[] name;
    name = NULL;
}

Test::Test(const Test& t)
    // :Parent(t)   // 如果是调用父类的拷贝构造函数则这样调
{
    delete[] name;
    name = new char[strlen(t.name) + 1];
    strcpy(name, t.name);
}

int main()
{
    Test * t1 = new Test(); // 调用默认构造函数
    Test t2 = *t1;          // 调用拷贝构造函数

    delete t1;              // 析构t1
    // delete *t2;          // 析构t2,此处不需要显式析构
    return 0;
}
class Test
{
public:
    Test(void);
    ~Test(void);
    Test& operator=(const Test& t);
private:
    char * name;
};

Test::Test(void)
{
    name = NULL;
}

Test::~Test(void)
{
    delete[] name;
    name = NULL;
}

Test& Test::operator=(const Test& t)
{
    // Parent::operator=(t);    // 如果是继承关系中调用父类的赋值运算符

    if (this != &t)             // 如果右边的对象与左边的对象不是同一对象时才赋值
    {
        delete[] name;
        name = new char[strlen(t.name) + 1];
        strcpy(name, t.name);
    }
    return *this;               // 返回的是该对象的引用
}

int main()
{
    Test* t1 = new Test();      // 调用默认构造函数
    Test t2;                    // 同上
    t2 = *t1;                   // 调用赋值运算符把t1的值赋给t2

    delete t1;                  // 析构t1
    // delete &t2;              // 析构t2,此处不需要显式析构t2
    return 0;
}

拷贝构造函数与赋值运算符的重载都是根据是否有指针类型的成员变量,如果有就需要重载来防止成员指针指向的地址是相同的。

Cocos2d-x之学习笔记

这是一个旋转动画效果

CCAction* rot = CCRotateBy::actionWithDuration(8, 720);

C++的重载、覆盖、隐藏

  1. 同一个类中的函数
  2. 函数名相同
  3. 参数不同
  4. virtual关键字可有可无
class Test
{
public:
    void post(const char* addr);
    void post(const char* addr, int port);  // 重载
};
  1. 不同的类中
  2. 函数名相同
  3. 参数相同
  4. 必须有virtual关键字
class Base
{
public:
    void post(const char* addr);
};

class Test: public Base
{
public:
    virtual void post(const char* addr);    // 覆盖
};
  1. 基于重载(不同的两个类)与覆盖之间(没有virtual关键字)
  2. 函数名相同,参数不同,virtual可有可无,不在同一个类中
  3. 函数名相同,参数相同,不在同一个类中,没有virtual关键字。
  4. 不同点:不在同一个类中与没有virtual关键字。
class Base
{
public:
    void post(const char* addr);
    void get(const char* addr);
};

class Test: public Base
{
    void post(const char* addr);                // 没有virtual关键字
    void get(const char* addr, int port);       // 参数不同,不在同一类中
};

C++的动态内存分配

char * mName;
void setName(const char * name)
{
    free(mName);                            // free用于释放malloc申请的内存空间,同时记住释放后应该把指针置NULL防止出现“野指针”。
    mName = (char*) malloc(sizeof(name) + 1);
    if (NULL != mName)
    {
        strcpy(mName, name);
    }
}
#include 

char * mName;
void setName(const char * name)
{
    delete[] mName;                         // delete用于释放new申请的内存空间,同时记住释放后应该把指针置NULL防止出现“野指针”。
    mName = new char[strlen(name) + 1 + 8]; // abcdefg为8个字符长度
    if (NULL != mName)
    {
        strcpy(mName, name);
        strcat(mName, "abcdefg");           // 往后面添加
    }

    // 最后释放内存应该使用 delete[] mName;因为时候使用了 new type[size];
}
</pre>
</section>

char strs[] = "abcdefg";

sizeof(strs);               // 输出8,sizeof能够计算出数组占用的内存容量,最后还有"\0"。
                            // 但有一点,数组作参数传递时会自动退化成指针,所以容量应该是sizeof(char) = 4。

strlen(strs);               // 输出7,strlen能够计算出字符,仅限于字符的长度,并不包括"\0"。
                            // 作strlen的参数时会自动退化为char*指针。

C++的const与pointer

const char* str;            // 常量指针,指向常量的指针,地址可变,值不可变。
// char const *str;         // 同上。

char* const str;            // 指针常量,地址不可变,值可变。

const char* const str;      // 两者,地址值均不可变。

@const@ 星前,常量指针,地址可变,值不可变。

@const@ 星后,指针常量,地址不可变,值可变。