C++把类的设计看成类型设计

简介: C++把类的设计看成类型设计

1.类设计的建议


C++和其它面向对象的语言一样,,定义一个类就定义了一个新的类型。重载函数和操作符,内存的分配与释放,对象的构造与析构,全部掌握在你的手上。所以在设计类的时候,要像语言的设计者设计内置类型一样小心。


好的类型拥有自然的语法,直观的语义和高效率的实现。如何高效地设计一个类呢? 以下的问题在几乎所有的类型设计中都会遇到,以及考虑这些问题会如何影响到你的设计:


(1) 新类型的对象要如何创建和销毁?


这决定了要如何写构造函数和析构函数,包括要使用什么内存分配和释放函数,即new还是new[],delete还是delete[]。请参见前面的文章C++要成对使用new和delete且采取相同形式


(2) 对象的初始化和对象的赋值应该有何差别?


这决定了你如何写,如何区别构造函数和赋值运算符,以及不要把初始化与赋值混淆,因为它们的语义不同,构造函数适用于未创建的对象,赋值适用于已创建的对象,这也是为什么我们要在构造函数中使用初始化列表而不使用赋值的原因。请参见前面的文章确定对象使用前已先被初始化C++中要完整拷贝对象


(3) 新类型的对象如果以传值方式传递,意味着什么?


要记住拷贝构造函数决定了你的类型是如何被传值的,因为传值会生成本地的拷贝。


(4) 什么是新类型的合法值?


通常情况下,并不是成员的任何数值组合都是合法的。要让数据成员合法,我们需要根据合法的组合,在成员函数中对数值进行检测,尤其是构造函数,赋值运算符和setter。这也会影响到使用它的函数会抛出什么异常。


(5) 新类型属于某个继承层级吗?


如果你的新类型继承自某个已有的类,你的设计将被这些父类影响到,尤其是父类的某些函数是不是虚函数。如果你的新类型要作为一个父类,你将要决定把哪些函数声明为虚函数,尤其要注意析构函数。具体请参见前面的文章C++中为多态基类声明虚析构函数


(6) 新类型允许进行什么样的转换?


新类型的对象将会在程序的海洋中与其它各种各样的类型并用,这时你就要决定是否允许类型的转换。如果你希望把T1隐式转换为T2,你可以在T1中定义一个转换函数,例如operator T2,或者在T2中定义一个兼容T1的不加explicit修饰的构造函数。如果希望使用显式转换,你要定义执行显示转换的函数。请参见前面的文章C++在资源管理类中提供对原始资源的访问


(7) 什么样的运算符和函数对新类型是有意义的?


这决定了你要声明哪些函数,包括成员函数,非成员函数,友元函数等。


(8) 禁止哪些标准函数?


如果不希望使用编译器会自动生成的标准函数,把它们声明为私有。请参见前面的文章如果不想使用编译器默认生成的函数,请明确拒绝它!


(9) 谁该取用新类型的成员?


这影响到哪些成员是公有的(public),哪些是保护的

(protected),哪些是私有的(private)。这也能帮你决定哪些类和函数是友元的,以及要不要使用嵌套类(nested class)。


(10) 新类型的隐藏接口是什么?


新类型对于性能,异常安全性,资源管理(例如锁和内存)有什么保障? 哪些问题是自动解决不需要用户操心的? 要实现这些保障,自然会对这个类的实现产生限制,例如要使用智能指针而不要使用裸指针。


(11) 新类型的通用性


如果想让你的新类型通用于许多类型,定义一个类模板(class template),而不是单个新类型。


(12) 新类型真的是你所需要的吗?


如果你想定义一个子类只是为了给基类增加某些新功能,定义一些非成员的函数或者函数模板更加划算。


2.总结



(1) 类的设计犹如类型的设计。在定义一个新类型之前,请确定你已经考虑过上面所讨论的全部建议。

相关文章
|
26天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
44 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
91 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
81 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
90 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
31 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
32 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
26 1
|
2月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
2月前
|
存储 编译器 C语言
【C++打怪之路Lv3】-- 类和对象(上)
【C++打怪之路Lv3】-- 类和对象(上)
18 0
|
2月前
|
存储 编译器 C语言
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:类与对象(上)