(侯捷C++)1.2面向对象高级编程(上)

1.整体结构

 2.三大函数:拷贝构造,拷贝赋值,析构

  • 拷贝构造:第一次出现对象,使用拷贝构造进行创建,例如:String s3(s1)。
  • 拷贝赋值:对象已经构造,重新赋值,例如s3 = s2。
  • 编译器有默认拷贝构造,但是提供的是浅拷贝,当有指针时,一定要自己定义拷贝构造,使用默认拷贝会出现问题。
  • 拷贝构造写法:String(const String& str);拷贝赋值写法:String& operator=(const String& str)。
  • 有指针的类一定要自己写拷贝构造和拷贝赋值,实现深拷贝,避免造成内存泄漏。
  • 拷贝赋值函数示例:
inline String& String::operator=(const String& str) {
    //检测自我赋值
    if(this == &str) return *this;

    //将原来清空
    delete []m_data;

    //分配空间
    m_data = new char[strlen(str.m_data) + 1];

    //复制
    strcpy(m_data, str.m_data);
    return *this;
}

3.堆栈及内存管理

  • stack是存在于某作用于的一堆内存空间,当调用函数时,函数本身就会形成一个stack用来放置它所接收的参数以及返回值。
  • heap是由操作系统提供的一堆全局内存空间,用new的方式动态获得,与之匹配用delete释放。
  • new先分配空间,再调用构造函数,delete先调用析构函数,再释放空间。
  • array new一定要搭配array delete。

  • stack objects的生命在作用域结束之际结束,因为离开作用域时会被自动析构。
  • static objects其生命在作用域结束之后仍然存在,直到整个程序结束。
  • global objects其生命在整个程序结束之后才结束,可以将其视为static objects,其作用域为整个程序。
  • heap objects生命在被delete之际结束。

总结 -- String类的实现过程

  •  类声明
class String {
public:
    String(const char* cstr = 0); //有参构造
    String(const String& str); //拷贝构造
    String& opreator= (const String& str); //拷贝赋值
    ~String(); 
    char* get_c_str() const {return m_data}; //方便cout接收

private:
    char* m_data; //使用指针可以动态分配大小
};
  • 类实现
inline String::String(const char* cstr = 0) {
    if(cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    }
    else { //未指定初值
        m_data = new char[1];
        *m_data = '\0';
    }
}

inline String::~String() {
    delete[] m_data;
}

inline String::String(const String& str) {
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.data);
}

//拷贝赋值
inline String& String::operator=(const String& str) {
    //检测自我赋值
    if(this == &str) return *this;

    //将原来清空
    delete []m_data;

    //分配空间
    m_data = new char[strlen(str.m_data) + 1];

    //复制
    strcpy(m_data, str.m_data);
    return *this;
}

4.扩展补充:类模板,函数模板及其他

(1)static补充:

  • 函数和数据均可以设为静态。
  • 静态数据要在类外进行定义。
  • 静态数据 / 函数只有一份,它不属于任何一个对象,被所有对象共享。
  • 静态函数只能处理静态数据,调用方式有两种:1.通过对象调用;2.通过类名调用。

代码示例:

 (2)将构造函数放在private的情况

  • 在单例模式下,将构造函数设为private,此时只允许创建唯一一个对象。
  • 单例模式设置静态函数,是外界获取对象的唯一窗口。

  •  进一步写法是将static A a写在getInstance中,如果没有人使用时a不会被创建。

(3)进一步补充类模板、函数模板

  • 类用法:template<typename T>后面跟class
  • 函数模板用法:template<typename T>后面跟函数

(4)进一步补充std

  • C++标准库中的对象和函数都是在std中定义的。

类与类之间的关系:组合 继承 委托

1.组合与继承

  • 组合表示has a,一个类拥有另一个类,container拥有component。
  • 其大小关系可以用下图来说明。

  •  构造顺序由内而外,Container的构造函数先调用Component的构造函数,然后才执行自己。
  • 析构函数由外而内,Container的析构函数先调用自己,然后调用Component的析构函数。
  • 组合关系的两个类的寿命一样。
  • 继承表示is a,一个类是另一个类中的一种,父类的数据会被完整的继承给子类。
  • 继承的语法为class A : public/private/protected class B。
  • 从结构上来看,子类的对象会包含着父类的成分。

  •  构造顺序由内而外,子类首先调用Base的构造函数,然后执行自己;析构顺序由外而内,子类的析构函数首先执行自己,然后调用Base的析构函数。

2.虚函数与多态

  • 非虚函数:不希望子类重新定义。
  • 虚函数:希望子类重新定义,并且它有默认定义。
  • 纯虚函数:希望子类一定要重新定义,对它没有默认定义。

3.委托相关设计

  • 一个类有另一个类,但只是有指向另一个类的指针,通过指针相连,可以称为Composition by reference。

  • 委托关系的两个类的寿命不一致,现有右边的类,才能有左边的类。
  • 当a、b、c都委托hello时,如果a想修改,需要重新复制一份给a用来修改,不能影响bc。
  • 常用于通过子类的对象调用父类的函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值