喜歡的朋友可以關注收藏一下: 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;
}
七、運行截圖