C++基础::类设计的几大原则

时间:2021-05-17 15:26:54
  • 类围绕成员变量进行设计,构造函数围绕成员变量构建类,成员函数围绕成员变量展开
    总之,在类的声明与实现中,成员变量居于中心的位置。

  • -

普通成员函数与虚函数

在一个抽象基类的内部可以有三种形式成员函数:

  • 普通成员函数
    所有派生类共享的函数实现,可以不给出实现(其实这样做没有意义),但当调用时自然会发生解析错误。
  • 虚函数
    必须给出实现,否则子类无法进行函数的重写。不同的子类可对其进行部分重写,根据需求。
  • 纯虚函数
    全部子类如果想成为能够实例化对象的类,必须实现父类的全部纯虚函数,否则子类仍是抽象类无法实例化对象。


C++基础::类设计的几大原则

class Base
{
public:
void foo(){} // 普通函数
virtual void fooA();
// 虚函数,交由DerivedA 实现
{
throw std::exception("cannot be called");
// 抛异常的目的是为了禁止DerivedB对象试图去调用(设计上)只能交由DerivedA对象调用的函数时
}
virtual void fooB();
// 虚函数,交由DerivedB实现
{
throw std::exception("cannot be called")
// 抛异常的目的是为了禁止DerivedA对象试图去调用(设计上)只能交由DerivedB对象调用的函数时
}
virtual void f() = 0;
// 纯虚函数
}
class DerivedA :public Base
{
public:
void fooA()
{ cout << "DerivedA::fooA()" << endl;}
void f(){}
}
class DerivedB :public Base
{
public:
void fooB()
{ cout << "DerivedB::fooB()" << endl;}
void f() {}
}

int main(int, char**)
{
DerivedA da;
DerivedB db;
da.foo();
db.foo(); // 调用父类的非虚成员函数

da.fooB(); // 抛异常
da.fooA(); // 多态,调用DerivedA的实现

db.fooA(); // 抛异常,
db.fooB(); // 多态,调用DerivedB的实现

Base* b = new DerivedA;
b->fooA(); // 多态
b->fooB(); // 抛异常

b = new DerivedB;
b->fooB(); // 多态
b->fooA(); // 抛异常

return 0;
}

使用UML类图,

即可以在设计好UML类图的前提之下进行代码的编写,也可边写代码,边设计类图。

从成员变量开始一个类的设计

成员函数围绕成员变量进行展开;

多个重载版本

可以有不同的重载版本(客户端调用的方便),实现时然后相互调用(为了编写代码的便捷)

这种重载不仅对于类的成员函数之间是如此,不同的全局函数也是如此,不妨以STL的算法中的sort为例进行展示:

从最终客户端的调用方式倒推类及其成员函数的设计

virtual 函数 几乎等同于需要在派生类进行重写的函数