c++ private 继承

继承相关知识:

private继承对派生类不可见(exist but not accessable)

private 和protect 继承不允许基类指针指向派生类(编译error: ‘BaseClass‘ is an inaccessible base of ‘DerivedClass‘

  • reinterpret_cast可以将private继承的派生类指针强制转化为基类指针(通过pbase = static_cast <BaseClass*>(pdrived);但是不要这么做,因为违反了pravite inheritance的原则!(dynamic_cast 不行,有人说static_cast 也可以,但是我试了不行:gcc4.8.1,c++1)


pravite继承类似于(相似,有区别)在基类添加了一个private成员变量(composition)尊重原作,原文链接

//E.g., the “Car has-a Engine” relationship can be expressed using simple composition
class Engine {
public:
  Engine(int numCylinders);
  void start();                 // Starts this Engine
};
class Car {
public:
  Car() : e_(8) { }             // Initializes this Car with 8 cylinders
  void start() { e_.start(); }  // Start this Car by starting its Engine
private:
  Engine e_;                    // Car has-a Engine
};

//The “Car has-a Engine” relationship can also be expressed using private inheritance:
class Car : private Engine {    // Car has-a Engine
public:
  Car() : Engine(8) { }         // Initializes this Car with 8 cylinders
  using Engine::start;          // Start this Car by starting its Engine
};

//使用 composition 还是 private inheritance?
//Use composition when you can, private inheritance when you have to
//"Isa" relationship should be modelled by inheritance, "has-a" should be modelled by containment:
class B : public A     // B "is-a" A
{
  ...
} 

class B
{
  ...
  private:
    A a_;     // B "has-a" A
}
//While public inheritence model an "is-a" relationship, private inheritance doesn‘t model anything at all, and is purely an implementation construct for sharing code with the class being inherited. This is better achieved by containment.

There are several similarities between these two variants:

In both cases there is exactly one Engine member object contained in every Car object

In neither case can users (outsiders) convert a Car* to an Engine*

In both cases the Car class has a start() method that calls the >start() method on the contained Engine object.

There are also several distinctions:

The simple-composition variant is needed if you want to contain several Engines per Car

The private-inheritance variant can introduce unnecessary multiple inheritance

The private-inheritance variant allows members of Car to convert a Car* to an Engine*

The private-inheritance variant allows access to the protected members of the base class

The private-inheritance variant allows Car to override Engine’s virtual functions

The private-inheritance variant makes it slightly simpler (20 characters compared to 28 characters) to give Car a start() method that simply calls through to the Engine’s start() method

Note that private inheritance is usually used to gain access into the protected members of the base class, but this is usually a short-term solution。

- Or A member (either data member or member function) declared in a protected section of a class can only be accessed by member functions and friends of that class, and by member functions and friends of derived classes,这就是为什么private继承可以访问protected的基类成员).



&ojb = class中的this指针,派生类指针转基类指针example:原文链接

class Animal { /* Some virtual members */ }
class Dog: public Animal {};
class Cat: public Animal {};

Dog     dog;
Cat     cat;
Animal& AnimalRef1 = dog;  // Notice no cast required. (Dogs and cats are animals).
Animal& AnimalRef2 = cat;
Animal* AnimalPtr1 = &dog;
Animal* AnimlaPtr2 = &cat;

Cat&    catRef1 = dynamic_cast<Cat&>(AnimalRef1);  // Throws an exception  AnimalRef1 is a dog
Cat*    catPtr1 = dynamic_cast<Cat*>(AnimalPtr1);  // Returns NULL         AnimalPtr1 is a dog
Cat&    catRef2 = dynamic_cast<Cat&>(AnimalRed2);  // Works
Cat*    catPtr2 = dynamic_cast<Cat*>(AnimalPtr2);  // Works

// This on the other hand makes no sense
// An animal object is not a cat. Therefore it can not be treated like a Cat.
Animal  a;
Cat&    catRef1 = dynamic_cast<Cat&>(a);    // Throws an exception  Its not a CAT
Cat*    catPtr1 = dynamic_cast<Cat*>(&a);   // Returns NULL         Its not a CAT.

大多数情况下,如果需要使用继承属性,则将数据定义为private,并且提供protected的接口,这样派生类可以定义自己的私有数据并且不会与基类的数据冲突,而且可以访问到基类的数据,更重要的是,在以后你需要对基类数据成员进行修改的时候不会使得派生类出错,这样可以最大化代码复用(只要不改变protected接口)。如果代码比较少,但是需要用到继承属性,可以定义少量protected数据,这样就是省去了定义一堆接口,简化代码。


要点:

虚析构函数:基类的析构函数必须是虚函数,防止内存泄露(slicing) ——make your destructor virtual if your class has any virtual functions(只要有虚函数)。Had Base’s destructor not been virtual, Derived’s destructor would not have been called – with likely bad effects, such as resources owned by Derived not being freed.

在设计函数的时候Pass-by-value should be avoided for objects:

myMethod (const SomeClass &object)  // good
myMethod (SomeClass object)         // bad: don‘t do this
  • 效率问题
  • objects passed by value through a base-class variable will in effect behave as a base-class object without the extended information defined by the derived class,如果参数是基类,则派生类会被截断。

Interface: A class with no data and where all functions are pure virtual functions(一般为public) is often called an interface.

纯虚函数的实现 派生类必须重新定义纯虚函数,但是有些共性的代码可以在纯虚函数中的实现完成,例如,可以用来执行某些具有共性的缺省设置,在派生类中显式执行BaseClass::pure_virtual_func即可;缺省设置也可以通过在基类中定义protected的成员函数,然后派生来能够在其成员函数中调用基类的protected函数来完成缺省设置。

派生类调用基类函数

void Der::f()
{
  Base::f();  // Or, if you prefer, this->Base::f();
}

Virtual Constructor? 就是纯虚函数的 clone(复制) 和 create(构造),但是在派生来中返回的为派生类的指针,而不是基类指针。That’s how to define a copy constructor or assignment operator for a class that contains a pointer to a (abstract) base class:

class Shape {
public:
  virtual ~Shape() { }                 // A virtual destructor
  virtual void draw() = 0;             // A pure virtual function
  virtual void move() = 0;
  // ...
  virtual Shape* clone()  const = 0;   // Uses the copy constructor
  virtual Shape* create() const = 0;   // Uses the default constructor
};
class Circle : public Shape {
public:
  Circle* clone()  const;   // Covariant Return Types; see below
  Circle* create() const;   // Covariant Return Types; see below
  // ...
};
Circle* Circle::clone()  const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle();      }

Never hide member functions that were public in my base class

C++ can’t distinguish between a pointer-to-a-thing and a pointer-to-an-array-of-things

class Base {
public:
  virtual void f();
};
class Derived : public Base {
public:
  // ...
private:
  int i_;
};
void userCode(Base* arrayOfBase)
{
  arrayOfBase[1].f();           // 此处如果传进来的是派生类,则编译器会按照基类的大小去在数组中找索引为1的指针,runtime error!使用std::array<Derived, 10> 能在编译的时候报错,而不是运行时出错
}
int main()
{
  Derived arrayOfDerived[10];
  userCode(arrayOfDerived);
  // ...
}

to be continued….

时间: 2025-01-01 20:57:41

c++ private 继承的相关文章

条款39:明智而审慎地使用private继承(use private inheritance judiciously)

NOTE: 1.private 继承意味 is-implemented-in-terms-of(根据某物实现出).它通常比复合(composition)的级别低.但是当derivated class需要访问protected base class的 成员,或需要重新定义继承而来的virtual函数时,这么设计是合理的. 2.和复合(composition)不同,private 继承可以造成empty base 最优化.这对致力于“对象尺寸最小化”的程度开发者而言,可能很重要.

Effective C++ 条款39 明智而审慎地使用private继承

1. public继承表明is-a的关系,要求接口的完全继承,而private继承表明"根据某物实现出的关系",要求仅仅继承实现,private继承有两个规则: 1). 经由private继承而来的基类的所有成员在派生类中都会变成private属性 2). 由于1),编译器不允许将派生类转为基类以防止对派生类private成员的非法访问. 2. 由条款38,private继承和复合具有相同作用——"根据某物实现出".两者之间,要尽可能使用复合,除非必要情况.必要情况

Effective C++ -----条款39:明智而审慎地使用private继承

Private继承意味is-implemented-in-terms of(根据某物实现出).它通常比复合(composition)的级别低.但是当derived class需要访问protected base class的成员,或需要重新定义继承而来的virtual函数时,这么设计是合理的. 和复合(composition)不同,private继承可以造成empty base最优化.这对致力于“对象尺寸最小化”的程序库开发者而言,可能很重要.

明智而审慎的使用private继承

private继承的意义在于“be implemented in turns of”. private继承与public继承时完全不同的,主要体现在两个地方 其一,public继承在子类中保持父类的访问权限,即父类中是public的成员函数或者成员便变量可,在子类中仍是public,对private或protected 的成员函数或成员变量亦是如此:但private继承则不是这样的,他破坏了父类红的访问权限标定,将之转成为private,这对子类本省并无影响,但却影响了子类的子类,子类的子类将无

private继承

class A { int a; int b; int fun(){ return a; } }; class B : private A { public: void funB() { int num = fun();//private继承派生类函数 基类为private根本访问不了,能访问protected和public } }; int main() { B b; return 0; }

(转)public、protect、private继承方式 C++

C里面的结构体内的成员不受任何机制保护,直接能用,比如StructtypeA.x;StructtypeA.y;StructtypeA.fun(); 而c++则不同,c++的类像强化型的结构体 public公有继承 protected保护继承 private私有继承 我们知道类的private和protected成员,在类外是不可以使用的.只有public成员可以在类外直接使用. 公有继承时,基类的private成员派生类也不可用,基类的public和protected成员在派生类中可直接使用.继

c++ public protected private 继承

1:访问控制 1.1 public 这类型成员可以被类本身函数访问,也可以被外部创建的类对象调用.子类对象与子类内部可以访问 1.2 protected类型成员,只能被类本身函数访问.外部创建的类对象没有访问权限.子类对象没有访问权限,子类内部可以访问 1.3 private类型成员,只能被类本身函数访问,外部创建的类对象没有访问权限.子类对象和子类内部都没有访问权限 class TestObject{ public: void Function(); void TestPublic(); pr

Effective C++ Item 39 明智而审慎地使用 private 继承

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:private 继承意味 is-implemented-in-terms of.它通常比 composition 的级别低. 但是当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的 virtual 函数时,这么设计是合理的 经验:和 composition 不同, private 继承可以造成 empty base 最

private 继承 真的没用吗??

private继承,在看到effective C++之前,我发现在我之前的代码里面,没有用到这个机制,但是认真回想起还是有一些影子. 大多数人认为private继承是没有用的,其实不然,在某些情况下,它也会带给你一些惊喜. 好,言归正传,之前已经数次提到过 public继承表示的是  "is   a "的关系,也就是说每一个derived对象D同时也是base对象,任何在base对象上的操作可以实施到derived对象身上. 例如: class Person{....}; class

private继承如何转换

<effective c++>中提到: 如果class之间的继承关系是private,编译器不会自动将一个derived class对象转换为一个base class对象. 如果不能转换那多态就没有意义了,所以肯定是可以转换的,不过转换发生在derived class内部: class B{ public: virtual void write(){ puts("B::write"); } }; class D:private B{ private: virtual voi