C++ 回忆录10 OOP

来源:互联网 发布:电视怎么切换网络电视 编辑:程序博客网 时间:2024/05/23 02:06

1.多态性只是应用于reference or pointer type .

2.base class 会使用virtual keyword 表明这个函数需要在子类中进行重定义.而没有virtual 的,则指明这个函数是让子类继承的而不需要修改. 如果子类需要重定义父类的virtual function,那么子类也需要包含这个重定义函数的声明.至于这个声明还需不需要再定义为virtual,则是可选的. 当然虽然父类声明了一个virtual function,子类也不是非要重定义,

如果不重定义,那也就是用父类的.

 虽然说子类重写父类的virtual function需要声明完全一样.但是如果return type 是父类的指针或引用,那么子类在重定义时,可以把返回值定义为子类的指针或引用.



3.动态绑定只发生在使用reference or pointer 去调用一个基类的virtual 函数的时候.,具体的调用is resolve at  runtime .要看runtime 时候实质指向的是base class or derived class.

By default,member functions are nonvirtual, calls to nonvirtual functions are resolved at compile time,call to virtual functions resolve at runtime.

nonstatic 的成员函数,不包括构造函数 可以被定义成virtual, virtual 关键字只是在类声明中使用,class body 定义就不需要virtual 了.

4.做为Root 基类,一般都会定义析构函数为virtual .


5.如果自己定义了带参数构造函数,那么编译器将不会自己生成默认构造函数,而此时如果子类也自定义了构造函数,如果这个自定义的构造函数没有调用父类的自定义构造函数,将会出错.

因为调用子类的自定义构造函数前,会首先调用父类默认构造函数

class A

{

   public :

      // A();   //注析掉

       A(int c);

};

class B :public A

{

  B();

    B(int c):A(c); //如果这里不显式的调用父类的构造函数,那么将会调用A() ,默认构造函数, 因为在构造一个子类前是首先构造父类的.

};


6.protected member 的一个重要属性.

class A

{

  protected:

  int k;

};

class B:public A

{

  public :

   void testProtected(const B & bobj,const A & aobj);

};

void A::testProtected(const B & bobj,const A & aobj)

{

    this->k=bobj.k;  //bobj.k 是合法的,因为是在B的类定义中,子类是可以访问父类的protected member

  this->k=aobj.k;// 这个则是不合法.

  

}

当然跳出了类定义,则也是不合法

const B & bobj;

 int cc=bojb.k;// 这中不合法.



8.一个类要被继承,那么他必须是首先已经定义好的,否则子类就看不到他的结构.怎么访问其成员.


9.前置定义不可以包括继承列表.

class A :public B; //error/

//should be defined like below:

class A;

class B;


10. nonvirtual function are resolve at compile time.

   DeriveClass obj;                (testNonVirtual 是非virtual function. BaseClass, and DeriveClass 都有定义.)

   BaseClass * basetype=obj;

  basetype->testNonVirtual();  就算basetype 的实质指向是DeriveClass,但还是调用BaseClass 的testNonVirtual

  obj->testNonVirtual();// 调用DeriveClass 的    testNonVirtual .

  以上两个调用在编译时候就已经决定了调用哪个. 因为nonvirtual function is resolve at compile time.


11.如何明确指示调用基类的virtual function

 Derive obj;

Base * base=&obj;

base->testVirtual();// 这个是在运行时决定的.

但是:

base->Base::testVirtual();//这个使用域限定符的则在编译的时候就知道调用的是基类的了.



12.public ,protected and private inheritance

  对继承过来的member 的access control 改变了,但是因为如果使用protected or private inheritance, 那么dynamic binding 是机制已经 不起作用.所以 都是使用public 继承.

class A

{};

class B:protected A

{};

A * base=new B();// 由于是protected inheritance, 这个会报编译错误.


13.friend and inheritance

class Base

{

  friend  class Frnd;

 private :

   int m_testfrnd;

};

class D:public Base

{

  private :

   int m_testdr;

};

class Frnd

{

  public:

    void testFrnd(Base b)

   {

  b.m_testfrnd; //可以访问.

}

void testFrnd2(D d)

{

    d.m_testfrnd;//还是可以访问的.

    d.m_testdr  ;//但是属于父类的成语则不可以了.因为父类没有声明friend.    //也就是说friend 关系不可以继承,不管是对friend class 还是

}

}

class DFrnd:public Frnd

{

   public:

   void testFrnd(Base b)

{

  b.m_testfrnd; //可以访问.   friend 不继承

}

}


14.static inheritance

  static 成员不管被继承多少次,都只有一份实例共享给整个继承链的所有类.

static 的成员如果不是const 则不可以在类声明里定义. 必须在类体定义.

 const 的成员,需要在声明的时候同时赋值.而且还要类体中定义.但不能赋值

class A

{

   public:

    static int membetrtyest();

   static int b;

  static const int c=5;

};

int A::b=5;

const int A::c; //注意必须再类体外定义.


15.

void testConversion(Base type1,Base & type2,Base * type3);

Derive doj;

testConversion(doj,doj,&doj);   这里面的转换是不一样的.  type1 , 当把doj传入后,doj会裁掉剩下Base 部分再传入,也就是一个Base对象,但是type2,type3则不是, runtime 时候会自动把相关的指针或引用转成 Base &, or Base *, 但doj 这个对象是没被转换,,,否则哪里动态binding.



16.使用Derived Object 去Initialize or Assign a Base Object.

 当我们 Initialize or Assign 一个对象的时候,其实我们在call 这个对象的Contructor or assignment operator.

那如果我们用一个Derived Object 去Initialize or Assign a Base Object 的时候会发生什么情况呢. 有两种.

1. 如果Base Object 定义了Copy Contructor (Using Derived object) or assignment operator from a Derived Object , 那就是call 这两个member function.

class Derived;

class Base

{

    Base (const Derived &);//

   Base &operator=(const Derived&);

};

2.没有定义这两个使用Derived 做参的函数,那么就是用默认的,也就是如下的

class Base

{

 Base (const Base &);   

Base & operator=(const Base &);    //这两个如果自己不重新定义的话,编译器会自动合成的.

};

这个时候如果用Derive Object 去初始化或者assign 这个Base  对象的话,有如下过程

Derived d;

Base b(d);

Base c=d;

1.call 默认的Copy Constructor or Assigment operator ,首先会将 Derive 引用转换成Base 的引用,这个在上一个总结点已经知道会自动执行的了.

2.会将Derive 这个对象Base 的那部分赋值给Base 的成员. 也就是说Slice down a Base part from the Derive Object.

那么结果就是b,c 这两个对象只是拥有了d 的Base 的那一部分....










原创粉丝点击