C++面向对象设计

C++面向对象程序设计的核心思想是数据抽象、继承和动态绑定。

C++中的成员函数分为两种,一种为虚函数,一种为非虚函数,虚函数是在运行时解析的,非虚函数是在编译时解析的。

2.派生类以及派生类向基类的类型

Quote item;
Bulk_quote bulk;

Quote *p = &item;  //p 指向Quote 对象
p = &bulk;            // p 指向bulk的Quote 部分
Quote &r = bulk;   // r 绑定到bulk的Quote 部分

 

派生类的构造函数

派生类也必须使用基类的构造函数来初始化它的基类部分。

每个类负责定义各自的接口,因此派生类不能直接初始化基类的成员。

无论从基类中派生出多少个派生类,每个静态成员都只有一个。

class Base;
class D1:public Base
class D2:public D1

在继承关系中,Base 是D1的直接基类,同时是D2的间接基类。要防止继承的发生。

防止继承

class NoDerived final   //不能作为基类

class Base

class Last final :Base
class Bad :NoDerved     //错误
class Bad2:Last            //last 是final 的

 

3.静态类型与动态类型

表达式的静态类型在编译时是已经知道的,动态类型则是变量或者表达式表示的内存中的对象的类型。

如果表达式既不是引用也不是指针,则它的动态类型永远和静态类型一致。

 

转换方式:

1、只能由派生类转换为基类。

2、基类不能转换诶派生类。

3、派生类向基类的自动类型转换只对指针或者引用有效。

 

4 虚函数

1、对虚函数的调用只有在运行的时候才能被解析。

2、被调用的函数是与绑定到指针或引用上的动态类型匹配的那一个,请注意,是指针或者引用在调用时才知道,通过对象调用的函数,在编译的时刻就确定了。

3、对非虚函数的调用是在编译时绑定的,通过对象进行的函数调用也是在编译的时候调用的

4、派生类中的虚函数,因为一旦某个函数被声明为虚函数了,则在派生类中它都是虚函数。比如说在基类中定义了为virtual, 在派生类中没有定义为virtual,实际上没有什么影响,只是为了好看而已。

5、正常情况下,派生类中虚函数的参数必须与基类中虚函数的参数一致,但是除了虚函数的返回类型是类本身的指针或者引用时的这种情况。

派生类向基类的可访问性这块儿还是没有看明白;(544页)

 

 

基类的可访问性

回避虚函数的机制

double undisconted = basep->Quote::net_price(42)

这样就会强行调用基类的net_price函数,不管base指向的是什么内容。

 

抽象基类

纯虚函数

 

访问控制与继承

友元和继承

友元关系不能传递,同样也不能继承,基类的友元,在访问派生类成员时不具有特殊性,类似,派生类的友元也不能随意访问基类的成员。

class Base
{
 protected:
   int  prot_mem;
};

class Sneaky:public Base
{
friend void clobber(Sneaky &);   //  sneakey::prot_mem 
friend void clobber(Base &);       //  base::prot_mem
int j;                                        //  
};

void clobber(Sneaky &s){
    s.j = s.prot_mem = 0;
}
void clobber(Base &b)
{
  b.prot_mem;
}
**:派生类的成员或友元只能通过派生类对象来访问基类的受保护成员,派生类对于一个基类对象中的受保护成员没有任何访问特权。

 

 

继承中的作用域

 

友元与继承

友元关系不能传递,同样也不能继承,

class Base
{
   protected:
   int  prot_mem;
   friend class Pal;  //重要,pal在访问Base的派生类的时候不具有特殊性。
};


class Sneaky:public Base
{
friend void clobber(Sneaky &);   //  sneakey::prot_mem
friend void clobber(Base &);       //  base::prot_mem
int j;                                        // 
};

class Pal { public : int f(Base b){ return b.prot_mem;} int f2(Sneaky s) {return s.j;}; //不能这么写,因为 Pal 不是 Sneaky的友元。 int f3(Sneaky s) {return s.prot_mem;};//OK, 因为 对基类的访问权限是由基类本身控制的,对于派生类中的基数部分也是如此。 };

  f3 的访问就是说明 Pal是Base的友元,所以Pal能够访问 Base对象的成员。

 

class D2 :public Pal
{
public :
int mem(Baseb b)
{
    return b.prot_mem; 
}
}; //不可以,因为友元函数不能继承。

总结一点,当一个类将另外一个类声明为友元时,这种友元关系只对做出声明的类有效果。


 

继承中的类作用域

 派生类的作用域位于基类的作用域之内,如果一个名字在派生类的作用域里面无法解析的时候,编译器会在外层的基类的作用域里面寻找该名字的定义。

Bulk_quote bulk;

cout<<bult.isbn();

首先在派生类的作用域里面找,如果派生类的作用域里面没有,再在它的基类的作用域里面找,基类没有,再在上一层的基类的作用域里面找。名字的查找是在编译的过程中实现的。

 

基类与派生类名字的关系

struct Base
{
 Base():mem(){}
protected:
 int mem;
};

struct Derived:Base{
Derived(int i) :mem(i){}
int get_mem() {retruen mem;}
protected:
int mem;  //这个将隐藏基类中的mem变量
};

不过想要使用基类中的变量,可以用作用域来实现的,如:

struct Derived:Base{

int get_base_mem() {return Base::mem;}

}; 这样是可以的。

 

当派生类成员和基类成员的形参不一致时,基类的成员也会被隐藏掉。

struct Base{
 int memfcn();
};

struct Derived:Base{
int memfcn(int);
};

Derived d;Base b;

b.memfcn();          //ok Base::memfcn();
d.memfcn(10);       //ok Derived::memfcn(int);
d.memfcn();          //ERROR   
b.Base::memfcn(); //OK

ERROR的是因为参数为空的memfcn被隐藏了。

 

转载于:https://www.cnblogs.com/zhangjingle/p/7821764.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值