【原創】C++_第三週_Rectangle類的初步實現(二)

喜歡的朋友可以關注收藏一下:  http://blog.csdn.NET/qq_31201973

本文實現了一個Shape類型並且派生出Rectangle類和Circle類,本文和上週有相似的地方也有不同,原版要求如下:

 

爲下面的 Rectangle 和 Circle 類重寫 getArea 虛函數。然後創建一個數組。 使用一個循環,生成 10 個 Rectangle、10 個 Circle,根據循環遍歷順序爲它 們設置 no 編號,位置、長、寬、半徑等其他信息取隨機 1~10 之間的整數值, 然後將它們加入到創建好的數組中。最後,將這個長度爲 20 的數組中所有面 積小於 50 的形狀刪除。將剩下的形狀組成一個新的數組返回。

注意: 1. 補齊任務所需的其他函數。2. 考慮正確的內存管理。3. 使用原生數 組,不使用 vector 等容器。

class Shape
{
int no;
public:
virtual int getArea()=0;
};
class Point
{
int x;
int y;
};
class Rectangle: public Shape
{
int width;
int height;
Point leftUp;
};
class Circle: public Shape
{
Point center;
int radius;
};


先談幾個細節:

一、class和struct

在c++裏class和struct功能很類似,但是我們一般用struct只用c語言延續的功能。

class默認是private,struct默認是public.

二、三種繼承的背後

衆所周知:

三種訪問權限

public:可以被任意實體訪問

protected:只允許子類及本類的成員函數訪問

private:只允許本類的成員函數訪問

 

三種繼承方式

public 繼承

protect 繼承

private 繼承

 

組合結果

基類中 繼承方式 子類中

public & public繼承 => public

public & protected繼承 => protected

public & private繼承 = > private

 

protected & public繼承 => protected

protected & protected繼承 => protected

protected & private繼承 = > private

 

private & public繼承 => 子類無權訪問

private & protected繼承 => 子類無權訪問

private & private繼承 = > 子類無權訪問

而關鍵就在這裏,基類private被子類繼承是無法訪問,而不是無法繼承。我用運算符sizeof()運算符算了一下大小發現它是可以繼承的只不過無法訪問。這樣除了public、private、protected還有一種隱藏的無法訪問,而無法訪問的成員是可以通過兩種方式恢復原權限。

方法一,使用using 語句,這是C++標準建議使用的方式 如: using Base-name::member;

方法二,使用訪問聲明,形式爲 base-class::member;, 位置在子類中適當的訪問聲明處。(注,只能恢復原有訪問權限,而不能提高或降低訪問權限)

三、出現的問題

在寫程序的時候我爲了保證通用性,寫了重載<< ,結果在定義Shape** 數組的時候發現兩種類型放到一個數組裏沒法訪問兩種類型的成員。在提交作業後在和別人討論發現,大多數人定義了一個print的虛函數,這樣實例化以後發現因爲互爲友元所以可以訪問自身的成員了,而重載<< 內也可以調用print函數。

而我因爲無法訪問,定義了一個struct包含了Rectangle和Circle類型,然後就可以訪問了。

四、c++11

涉及c++11的問題請看第一週文章的解釋。

五、相關文章

1.http://www.cppblog.com/shongbee2/archive/2009/04/01/78554.html#post

2.http://www.cnblogs.com/ustc11wj/archive/2012/08/11/2637316.html

3.http://www.cnblogs.com/bizhu/archive/2012/07/20/2601303.html

4.http://blog.csdn.net/stay4it/article/details/70879884

5.http://www.cppblog.com/airtrack/archive/2012/09/16/190828.aspx

6.http://blog.csdn.net/huang_xw/article/details/8764346

7.http://www.cnblogs.com/york-hust/archive/2012/06/01/2530799.html

8.http://www.cnblogs.com/ider/archive/2011/07/31/cpp_cast_operator_part4.html

9.http://blog.sina.com.cn/s/blog_9ce5a1b5010131nj.html

10.http://blog.csdn.net/weizhee/article/details/562833

11.http://wenda.so.com/q/1382868367063692?src=140

六、我的代碼

//	本文件名  class_define.h			我的編程環境VS2013
/*		本程序的註釋代表僅代表個人理解,不一定完全正確,全是我親自敲上去的,如有錯誤請聯繫我。						*/
/*	本程序隨機數生成器類和變參數print()函數使用了C++11 的標準,可能有的編譯器不能編譯通過,我會截圖一下編譯結果	*/
/*	本程序沒有使用原型的設計模式,而是採用結構體的模式	*/
#ifndef __CLASS_DEFINE_H__
#define __CLASS_DEFINE_H__
#include<iostream>
#include<random>
using namespace std;
const double PI = 3.1415926;			//π


namespace guo
{
	template<typename T>
	class Shape
	{
	private:
		int no;					//給每個Shape類及其子類按創建對象順序標號
	public:
		static int count;		//統計當前存活的Shape類及其子類按創建對象(數目)
		Shape() :no(++count) { ; }							//構造函數
		Shape(const Shape& other) :no(++count)	{ ; }		//拷貝構造函數
		Shape& operator=(const Shape& other)
		{
			if (this == &other)
			{
				return *this;
			}
			else
			{
				no = other.no;
				return *this;
			}
		}
		~Shape() { count--; }			//當前存活的Shape類及其子類按創建對象(數目減一)
		int get_no() const { return this->no; }
		static void set_count(const int x)	{ count = x; }
		virtual T getArea() = 0;		//得到面積


	};

	class Point
	{
	private:
		int x;
		int y;
	public:
		Point(int x1 = 0, int y1 = 0) : x(x1), y(y1)	{; }	//	構造函數,支持對象符合
		int get_x() const { return x; }
		int get_y() const { return y; }
	};

	class Rectangle : public Shape<double>
	{
	private:
		int width;
		int height;
		Point leftUp;
	public:
		Rectangle(int width1 = 0, int height1 = 0, int x1 = 0, int y1 = 0);			//構造函數	
		//Rectangle(const Rectangle& other);							//拷貝構造函數
		Rectangle& operator=(const Rectangle& other);				//拷貝賦值函數
		~Rectangle();												//析構函數 只聲明不定義會出無法解析的錯誤
		int get_width() const { return width; }
		int get_height() const { return height; }
		const Point& get_leftUp() const { return leftUp; }
		virtual double getArea()	{ return (this->height)*(this->width); }				//得到面積
		friend Rectangle& __doequ(Rectangle*, const Rectangle&);	//賦值實際運算函數
		//int get_no() const { return no; }
	};

	class Circle : public Shape<double>
	{
	private:
		Point center;
		int radius;
	public:
		Circle(int radius1 = 0, int x2 = 0, int y2 = 0);			//構造函數
		~Circle();												//析構函數 只聲明不定義會出無法解析的錯誤
		Circle& operator=(const Circle& other);				//拷貝賦值函數
		int get_radius() const { return radius; }
		const Point& get_center() const { return center; }
		virtual double getArea()	{ return PI*(this->radius)*(this->radius); }		//得到面積
	};

	class Rand_int				//等概率整數的隨機數生成器		隨機生成器由引擎(負責生成一組隨機值或者僞隨機數)和一種分佈(負責把引擎產生的值映射到某個數學分佈上)
	{
	public:
		Rand_int(int low, int high) : dist{ low, high }
		{
			;
		}	 		//構造函數  初始化隨機數範圍
		int operator()(){ return dist(re); }		//操作符() 重載	得到一個隨機int
	private:
		default_random_engine re;		//默認隨機引擎
		uniform_int_distribution<> dist;//分佈:生成的所有整數概率相等

	};

	typedef struct twotype
	{
		Rectangle p;
		Circle q;
	}twotype;

/************************************						The Rectangle class member function define.						************************************/

	inline Rectangle::Rectangle(int width1, int height1, int x1, int y1) : width(width1), height(height1), leftUp(Point(x1, y1))	//Rectangle類的構造函數,需要Point有構造函數
	{
		;
	}

	inline Rectangle::~Rectangle()
	{
		;
	}

	Rectangle& Rectangle::operator=(const Rectangle& other)
	{
		if (this == &other)
		{
			return *this;
		}
		Shape<double>::operator=(other);
		this->width = other.width;
		this->height = other.height;
		this->leftUp = other.leftUp;
		return *this;
	}




/****************************************************************************************************************************************************************/

/************************************						The Circle class member function define.						************************************/

	inline Circle::Circle(int radius2, int x2, int y2) :radius(radius2), center(Point(x2, y2))
	{
		;
	}

	inline Circle::~Circle()
	{
		;
	}

	Circle& Circle::operator=(const Circle& other)				//拷貝賦值函數
	{
		if (this == &other)
		{
			return *this;
		}
		Shape<double>::operator=(other);
		center = other.center;
		radius = other.radius;
		return *this;
	}

/****************************************************************************************************************************************************************/
	
/*							print函數							*/
	void print()
	{
		;
	}
	template<class type, class... types>		//class 的定義和 typename 類似 都是說這個模板參數定義的是一個類,而不是變量.class type 和	class... types      type 和 types 是模式 , ...  是包擴展
	void print(const type& x, const types&... next)
	{
		cout << x << endl;
		print(next...);
	}
/****************************************************************************************************************************************************************/


	//Rectangle** create_array(Rectangle **buff, const int& count)
	//{
	//	Rand_int randx{1,10};
	//	for (int i = 0; i < count; i++)
	//	{
	//		buff[i] = new Rectangle(randx(), randx(), randx(), randx());
	//	}
	//	//for (int i = (count / 2); i < count; i++)
	//	//{
	//	//	buff[i] = new Circle(randx(), randx(), randx());
	//	//}
	//	return buff;
	//}

	//Circle** create_array(Circle **buff, const int& count)
	//{
	//	Rand_int randx{ 1, 10 };
	//	for (int i = 0; i < count; i++)
	//	{
	//		buff[i] = new Circle(randx(), randx(), randx());
	//	}
	//	return buff;
	//}

	ostream& operator<<(ostream& os, guo::Rectangle& rec)			//The Rectangle class operator function. 
	{
		return os << ' ' << "NO." << rec.get_no() << ' ' << '(' << "長=" << rec.get_height() << ',' << "寬=" << rec.get_width() << ',' << "面積=" << rec.getArea() << ')' << "      " << "座標=" << '(' << rec.get_leftUp().get_x() << ',' << rec.get_leftUp().get_y() << ')' << endl;
	}

	ostream& operator<<(ostream& os, guo::Circle& cir)			//The Rectangle class operator function. 
	{
		return os << ' ' << "NO." << cir.get_no() << ' ' << '(' << "半徑=" << cir.get_radius() << ',' << "面積=" << cir.getArea() << ')' << "      " << "座標=" << '(' << cir.get_center().get_x() << ',' << cir.get_center().get_y() << ')' << endl;
	}

	twotype* create_array(twotype *buff, twotype *buff2, const int& count)
	{
		Rand_int randx{ 1, 10 };
		
		print("初次創建:");
		for (int i = 0; i < count; i++)
		{
			Rectangle a(randx(), randx(), randx(), randx());
			Circle b(randx(), randx(), randx());
			buff[i].p = a;
			buff[i].q = b;
			cout << buff[i].p << endl;
			cout << buff[i].q << endl;
		}
		print("刪除面積小於之後:");
		for (int i = 0; i < count; i++)
		{
			if (buff[i].p.getArea() >= 50)
			{
				buff2[i].p = buff[i].p;
				cout << buff2[i].p << endl;
			}
			if (buff[i].q.getArea() >= 50)
			{
				buff2[i].q = buff[i].q;
				cout << buff2[i].q << endl;
			}
		}
		

		return buff;
	}

}

#endif

 

//	本文件名  main.h			我的編程環境VS2013
/*		本程序的註釋代表僅代表個人理解,不一定完全正確,全是我親自敲上去的,如有錯誤請聯繫我。						*/
/*	本程序隨機數生成器類和變參數print()函數使用了C++11 的標準,可能有的編譯器不能編譯通過,我會截圖一下編譯結果	*/
/*	本程序沒有使用原型的設計模式,而是採用結構體的模式	*/
#include<iostream>
#include"class_define.h"
#include<random>

using namespace std;
int guo::Shape<double>::count = 0;
const int x = 10;

int main(void)
{
	//guo::Rectangle r1{ 2, 2, 1, 1 };
	//guo::Circle c1{ 2, 3, 4 };
	//guo::Rectangle *a1[x];
	//guo::Circle *a2[x];
	guo::twotype a3[x];
	guo::twotype buff2[x];


	//cout << "矩形r1:" << r1 << endl;

	//cout << "圓形c1:" << c1 << endl;

	//cout << "sizeof(r1)=" <<sizeof(r1) << endl;		//繼承證明驗證

	/*guo::print("請輸入創建數組的大小(20):");*/		//自定義print()函數驗證
	//cin >> x;

	guo::create_array(a3, buff2, x);					//創建刪除一體

	/*printArray(a3, x);*/



	getchar();
	getchar();
	return 0;
}


七、運行截圖

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章