1. 工厂方法优于构造函数<使用工厂方法代替构造函数>
优点:
(1)工厂方法返回值并不一定是声明类型的实例,可以是它的子类实例
代码更加简洁。
------(更好体现多态)
(2)每次返回的对象也并不一定都是新创建的对象,完全可以将其缓存。相比每次调用构造函数都创建一个实例,而工厂方法可以缓存以前创建的对象,并重用它们,节省内存。
(3)对同步的控制,在工厂方法中可以将创建对象前后的相应代码进行统一处理;构造函数对于这种情况就无能为力了
(4)工厂方法支持参数化的返回类型,但构造函数是做不到这一点的
(5)工厂方法是一个方法,一个方法并不会限定返回值实例的类型,可以是类,也可以是接口;但构造函数的返回值却一定是指定的实例。
2.让所有内容都不可更改
设计的类如果不考虑让其拥有子类,就应该让这个类不能被继承
(1)private修饰
(2)转换,使用工厂方法
(3)final修饰,强制外部无法继承此类
#include <iostream>
using namespace std;
template <typename T>
class Base{
friend T;
private:
Base(){
cout << "base" << endl;
}
~Base(){}
};
class B:virtual public Base<B>{ //一定注意 必须是虚继承
public:
B(){
cout << "B" << endl;
}
};
class C:public B{
public:
C(){} //继承时报错,无法通过编译
};
int main(){
B b; //B类无法被继承
//C c;
return 0;
}类Base的构造函数和析构函数因为是私有的,只有Base类的友元可以访问,B类在继承时将模板的参数设置为了B类,所以构造B类对象时们可以直接访问父类(Base)的构造函数。
为什么必须是虚继承(virtual)呢?
参见 c++Primer 4th 第17.3.7节 特殊的初始化语义
通常每个类只初始化自己的直接基类,但是在虚继承的时候这个情况发生了变化,可能导致虚基类被多次初始化,这显然不是我们想要的。(例2: AA,AB都是类A的派生类,然后类C又继承自AA和AB,如果按之前的方法会导致C里面A被初始化两次,也会存在两份数据)
为了解决重复初始化的问题,从具有虚基类的类继承的类在初始化时进行了特殊处理,在虚派生中,由最低层次的派生类的构造函数初始化虚基类。在我们上面的例1中就是由C的构造函数控制如何进行虚基类的初始化。
为什么B类不能被继承?
回到例1,因为B是Base的友元,所以B对象可以正常创建,但由于B使用了虚继承,所以如果要创建C对象,那么C类的构造函数就要负责虚基类(Base)的构造,但是Base的构造函数是私有的,C没有访问的权限(ps:友元关系不能被继承的),所以例1中的C类在编译时就会报错。这样B类就不能被继承了。
C++11
#include "stdafx.h" #include <iostream> class B1 final {}; class B { public: virtual void f() const { std::cout << __FUNCTION__ << std::endl; } virtual void fun() { std::cout << __FUNCTION__ << std::endl; } }; class D : public B { public: virtual void f(int) { std::cout << "hiding: " <<__FUNCTION__ << std::endl; } virtual void fun() override final { std::cout << __FUNCTION__ << std::endl; } }; class D2 : public D { public: virtual void f() const { std::cout << __FUNCTION__ << std::endl; } }; int _tmain(int argc, _TCHAR* argv[]) { D2 d2; D d1; B *b = &d1; b->f(); b->fun(); d1.f(10); d2.f(); d2.fun(); return 0; }
3.避免滥用setter方法
4.方法优于字段
5.尽可能用namespace来公开功能
6.赋予对象创建者更多权利
7.避免暴露深层次的继承
继承只是增加功能,尽量不重写功能
转载请注明原文地址: https://ju.6miu.com/read-402.html