Effective C++: public继承(is-a).

本文深入探讨了C++中虚函数的使用及其在面向对象编程中的重要性,包括虚函数的定义、作用、以及基类与派生类之间的转换。通过具体代码示例,展示了如何实现和利用虚函数来增强代码的灵活性和可扩展性。

何为(is-a)?

也就是能执行在Base-class(基类)身上的操作,都能执行在Derived-class身上,但是能执行在Derived-class身上的操作并不一定能执行在Base-class上面.

 case 1: 在抽象基类中声明并且实现纯函数,派生类中不再实现,此时无论是派生类还是基类都不能作为对象,否则就会报错.

#include <iostream>

class Base {
public:
	Base() = default;
	Base(const int& val) :value(val) {}
	Base(const Base& other) :value(other.value) {}
	Base(Base&& other) :value(other.value) {}
	
	Base& operator=(const Base& other)
	{
		this->value = other.value;
		return *this;
	}

	Base& operator=(Base&& other)
	{
		this->value = other.value;
		return *this;
	}

	virtual ~Base() = default; //注意这里作为基类的情况下必须把构造函数作为虚函数.
	                                         //在析构函数调用的时候就能保证析构正确的内容.

	virtual void print()const  //virtual function
	{
		std::cout << this->value << std::endl;
	}

	void word(const int& number)const //!
	{
		std::cout << number << std::endl;
	}

private:
	int value{ 10 }; //在调用默认构造函数的情况下会调用这里的初始化语句.
};

class PureBase { //由于有 pure virtual function因此该class并不能当对象使用.
public:
	virtual ~PureBase() = default;
	virtual void pureVirFunc()const = 0; //pure virtual function!

protected: //注意我们都定义为了: protected
	             //因为由于含有pure virtual function, 因此我们不能使用PureBase,把下面的函数都定义为protected的更加合适.
	PureBase() = default;
	PureBase(const int& num) :number(num),theNum(num+10) {}

	//PureBase(const PureBase& other) :number(other.number), theNum(other.theNum){}
	//PureBase(PureBase&& other) :number(other.number), theNum(other.theNum) {}
	//const PureBase& operator=(const PureBase& other)
	//{
	//	this->number = other.number;
	//	this->theNum = other.theNum;
	//	return *this;
	//}
	//const PureBase& operator=(PureBase&& other)
	//{
	//	this->number = std::move(other.number);
	//	this->theNum = std::move(other.theNum);
	//	return *this;
	//}

	const int& getPrivateData()const
	{                                                     
		return (this->theNum);
	}

	int& getPrivateData()
	{
		return (this->number);
	}

	template<typename T>
	void setData(T&& number)
	{
		this->theNum = std::forward<T>(number);
	}

	int number{ 20 }; //注意数据这里也是: protected的.
	                           //为了给派生类可见,而且确保派生类能够修改派生来的数据. 

private:
	int theNum{ 30 };
};

void PureBase::pureVirFunc()const //注意这里我们给上面的 pure virtual function 提供了定义.
{                                                      //为什么要提供定义呢! 因为需要访问PureBase的private的成员.
	std::cout << "pureVirtualFunction In PureBase: " << this->theNum << std::endl;
}





class DerivedOne : public Base, public PureBase {
public:
	DerivedOne() = default;
	DerivedOne(const int& v) : Base(v), PureBase(v), data(v) {}//注意这里我们使用了: 基类中的protected的构造函数.
	virtual ~DerivedOne() = default;

	DerivedOne(const DerivedOne& other)
		:Base(other),
		data(other.data)
	{
		this->number = other.number;
		this->setData(other.getPrivateData());
		//PureBase::PureBase(other); //由于PureBase是个abstract-class因此并不能使用.
	}

	DerivedOne(DerivedOne&& other)
		:Base(other),
		data(other.data)
	{
		this->number = other.number;
		this->setData(std::move(other.getPrivateData()));
	}

	DerivedOne& operator=(const DerivedOne& other)
	{
		Base::operator=(other);
		this->number = other.number;
		this->setData(other.getPrivateData());

		return *this;
	}

	DerivedOne& operator=(DerivedOne&& other)
	{
		Base::operator=(other);
		this->number = std::move(other.number);
		this->setData(std::move(other.getPrivateData()));

		return *this;
	}

	virtual void pureVirFunc()const override
	{
		std::cout << "pureVirtualFunction In Derived Class: " << this->data << std::endl;
	}

	virtual void print()const override
	{
		std::cout << "DerivedOne-class: " << this->number << std::endl;
	}

	void print(const int& theVal, int rightVal)const //注意这里,并不会影响虚函数的动态调用.
	{
		rightVal = 100;
		int x{};
		x = 200;
		std::cout << "theVal: " << theVal << std::endl;
	}

	void word()const  //这里会覆盖继承而来的: 所有同名的函数,不管参数返回类型如何, 只要函数名字一样就会被覆盖.
	{
		std::cout << "therWordInDerivedClass" << std::endl;
	}

private:
	int data{ 40 };
};


int main()
{
	Base base{};
	DerivedOne derived;

	//case 1:  不能创建一个abstract-class作为对象.
	//PureBase pureBase{};

	//case 2:  可以作为动态调用的对象.
	PureBase& pB{ derived };
	pB.pureVirFunc();

	//case 3
	DerivedOne de{ 40 };
	derived = de;

	//case 4: 派生类的同名函数隐藏了,基类中的同名函数,不管返回类型,还有参数如何.
	derived.word();
	//derived.word(20); //error!
	derived.Base::word(20); //但是我们可以强制调用.

	return 0;
}

 

case2: 基类向派生类转换其中 只有派生类中基类部分被初始化了, 派生类自己的部分处于未定义状态.

 #include <iostream>
#include <string>
class Base{
 private:
  int number_;
  
  public:
   explicit Base(const int& n_):number_(n_){}
   
   virtual ~Base()=default;
   
   virtual void print()const
   {
    std::cout<<this->number_<<std::endl;
   }
   
   void set_number()noexcept
   {
    this->number_ = 1;
   }
};
class InheritBase : public Base{
 private:
  std::string str_;
  
  public:
   InheritBase()=default;
   
   InheritBase(const int& number_, const std::string& s_):Base(number_),str_(s_){}
   
   void println()const
   {
    std::cout<<this->str_<<std::endl;
   }
   
   ~InheritBase()=default;
};
int main()
{
 Base* ptr_b = new InheritBase(520, "shihuawoaini");
 ptr_b->set_number();
 ptr_b->print();
 
 Base* ptr_b2 = new Base(100);
 InheritBase* ptr_i = static_cast<InheritBase*>(ptr_b2);
 //ptr_i->println(); //虽然可以运行但是会在运行中出错,因为InheritBase中的部分是未被初始化的.
 ptr_i->print(); 
 
 
 delete ptr_b2;
 delete ptr_b;
 return 0;
}

 

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/647693

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值