virtual与其他成员函数--《C++ primer》 笔记

从派生类到基类的转换

基本使用方法:

double print_total(const Item_base&, size_t){std::cout << "test" << std::endl;    return 0.3;}
	//function with an Item_base reference parameter
	Item_base item;				//object of base type
	//ok:use pointer or reference to Item_base to refer to an Item_base object
	print_total(item, 10);		//passes reference to an Item_base object
	Item_base *p = &item;		//p points to an Item_base object
	Bulk_item bulk, *q;				//object of derived type
	//ok:can bind a pointer or reference to Item_base to a Bulk_item object
	print_total(bulk, 10);		//passes reference to the Item_base part of bulk
	p = &bulk;					//p points to the Item_base part of bulk
q = &bulk;
std::cout << p << " : " << q << std::endl;//地址是相同的

亮点不是传递参数,是指针,基类指针p也能指向派生类派生类对象拥有基类子对象,那么p指向的算派生类对象还是基类子对象?至少和q地址一样

地址相同也可能说明类中空间存储的顺序是先放基类子对象,再放派生类对象的那部分。


关于覆盖虚函数机制:

Item_base *baseP = &derived;
double d = baseP->Item_base::net_price(42);//错误的原例
d = baseP->net_price(42); //对照组

上边这个书中烂例子(p481)表达出来的东西是错误的,不是说Item_base::将强制调用基类版本,而是使用Item_base指针本身就强制转换过了,这个过程已经“强制”的覆盖了(应该说指向的是派生类对象的基类子对象),编译器都将它当作基类对象(p480)。

只有下面例子的Bulk_item指针才能表达出这个覆盖作用。

Bulk_item *derivedP = &derived;

	d = derivedP->net_price(42);
	std::cout << d << std::endl;
	d = derivedP->Bulk_item::net_price(42);
	std::cout << d << std::endl;
	d = derivedP->Item_base::net_price(42);
	std::cout << d << std::endl;

多态性

//主调函数
void print_total(std::ostream &os, const Item_base& item, size_t n){
    os << "ISBN: " << item.book() //calls Item_base::book
        << "\tnumber sold: " << n << "\ttotal price: "
        //virtual call:which version of net_price to call is resolved at run time
        << item.net_price(n) << std::endl;//被调用的虚函数net_price()
}

//测试virtual函数的多态性~测试代码:
    Item_base base;
    Bulk_item derived;
    //print_total makes a virtual call to net_price
    //手动调用基类做对照
    std::cout << base.net_price(10) << std::endl;
    std::cout << derived.net_price(10) << std::endl;
//传递引用
    print_total(std::cout, base, 42);    //calls Item_base::net_price
    print_total(std::cout, derived, 42);    //calls Bulk_item::net_price
    


虚函数与默认实参概念:默认实参是编译时确定的,如果一个调用省略了具有默认值的实参(how?就是不输入参数的调用例如fcn()吧),则所用的值由调用该函数的类型(谁调用?是在类内调用函数还是传递类来调用函数)定义,与对象的动态类型无关(动态类型有什么玄机

如果用指针或引用调用虚函数,基类指针调用基类虚函数声明中指定的值,派生类使用派生类的。

====================================================================================================================================语言障碍太大了,简单的道理被作者费力的翻译成复杂的语言,还要有个中文翻译,最后复杂的语言被读者费力解读,最后在脑中还是演变成简单几句话的理解~!需要一个更好的方法更快速的学习,还不遗漏书中重要的逻辑(其实还是粗略的看最快,重点应该以后回来查阅,书是自己的。but,有时候太粗略的看还不能理解,毕竟示例代码有限,要自己写不少实验代码,读太粗略自己写不出来就完蛋,恼火~!)

书中那几句废话不就是说,默认实参和这个函数的多态是配套的么(不是本来默认实参就该是函数的一部分么,真搞不懂为什么弄一大堆复杂的语言来描述废话,难道默认实参不是绑定于函数的(mark)),你调用基类版本的virtual函数,当然是使用基类的默认实参,调用派生类版本的就用派生类版本的默认实参,另外,指针和引用也遵循这个原则(前文也有了,指针的作用实际上是个小强制转换,这个“强制转换”是因,调用转换成的基类或者派生类类型的virtual函数从而使用该版本的默认实参是果。。)

/*virtualArgument.cpp*/
	Item_base base;
	Bulk_item derived;
//如果输入了实参,比如11,那就传递11,基类派生类一样
    std::cout << base.net_price(11) << std::endl;
    std::cout << derived.net_price(11) << std::endl;
//如果不输入实参,使用默认实参,根据基类和派生类的调用情况~各找各妈去	
std::cout << base.net_price() << std::endl;
std::cout << derived.net_price() << std::endl;
Item_base *baseP = &derived;//利用指针把派生类“转换”成基类std::cout << baseP->net_price() << std::endl;//Bulk_item *deriveP = &base;//不能把基类往派生类转


====================================================================================================================================

pe15_8.cpp

找错修正题,搞不定了(mark

到底谁访问基类,谁虚,弄得太乱了

//解释程序,找问题
#include<iostream>
struct base{//另一处提示: note:                 base::base(const base&)
	base(const std::string &s): basename(s) {}//和derived错误提示绑定的提示: note: candidates are: base::base(const std::string&)
	std::string name(){return basename;}
	virtual void print(std::ostream &os) {os << basename;}
private://默认public
	std::string basename;
};
struct derived: public base{//题中错误:没有类派生列表
	derived(int i): mem(i){}//错误提示也很令人惊讶: error: no matching function for call to ‘base::base()’
	void print(std::ostream &os) {//题中错误:函数体内的print()调用的参数列表不像是使用,而是声明(ostream &os)
base::print(os);//题中错误:没用base::强制调用基类的print(),不过我加了也不对。。。。恼火~!
os << " " << mem;//而且参数列表中的局部变量os,无法给外边的os << " " << mem;使用
}

private:
	int mem;
	
};

int main(){
	base b1("jet");
	derived d1(10);
	b1.print(std::cerr);//玩的,cerr也是显示
	d1.print(std::cout);
}

习题15.9

因为15.8没解决,15.9也晾着

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值