- 不要重新定义继承而来的非virtual函数。
- 不要重新定义继承而来的缺省参数值。
// 让非virtual函数指定缺省参数,而private virtual函数负责工作。
class Base{
public:
enum BaseType{ A, B, C};
void show(BaseType type = A) const{
doShow(type);
}
private:
virtual void doShow(BaseType type) const = 0;
}
class Derived : public Base{
public:
...
private:
virtual void doShow(BaseType type) const;
}
- 当认为private继承是表现两个类之间的关系时,才使用它。
class Empty{};
class anInt{
private:
int x;
Empty e;
};
// c++会默认安插一个char到空对象中
sizeof(anInt) > sizeof(int); // return true
class anIntDerived : private Empty{
private:
int x;
}
//空白基类最优化,一般在单一继承下可行
sizeof(anInt) == sizeof(int); // return true
- 谨慎使用多重继承
class A{
public:
void show();
};
class B{
private:
void show();
};
class C: public A, public B{
...
};
C c;
c,show(); // 歧义,编译器不知道调用哪个show()
c.A::show(); // 正确
c.B::show(); // 错误,无法调用private
同时我们还要注意菱形多重继承。
class A{...};
class B : virtual public A{...};
class C : virtual public A{...};
class D : public B, public C{...};
- 注意名称可视性,基类的名称覆盖问题。
class B{
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
};
// case 1
class D : public B{
public:
virtual void mf1();
void mf3();
}
// 注意,只要同名就会被掩盖
D d;
int x;
d.mf1();
d.mf1(x);// 错误。D::mf1掩盖了B::mf1
d.mf2();
d.mf3();
d.mf3(x);// 错误。D::mf3掩盖了B::mf3
// case 2
class D : public B{
public:
using B::mf1;
using B::mf3;
virtual void mf1();
void mf3();
}
// 这时候就会正常调用
D d;
int x;
d.mf1(); // D::mf1
d.mf1(x);// B::mf1
d.mf2();// B::mf2
d.mf3();// D::mf3
d.mf3(x);// B::mf3
// case 3
class D : public B{
public:
virtual void mf1() { B::mf1(); }
}
// 利用隐式inline
D d;
int x;
d.mf1(); // D::mf1
d.mf1(x);// 错误,B::mf1()被掩盖