您的位置:首页 > 编程语言 > C语言/C++

C++面向对象设计之一(面向对象思想)

2018-01-03 16:12 375 查看
1.面向对象思想

看到面向对象,我们的第一反应就是类和对象,可是怎么设计类和对象呢?应该考虑三个要素:组件,属性和行为。例如,假设桔子是一个类,这个桔子都由什么组成呢?由桔子皮,果肉还有桔子核,你要吃桔子就要去掉桔子皮(这是一个行为)。再看桔子的共有特征——属性,桔子都有颜色,味道,重量等等属性。最后看行为,能对桔子做什么,榨汁,滚动,投掷,去皮吃,这就是行为。把握这三点在设计对象的时候会有比较清晰的思路。再看一个例子:飞机这个类,飞机由驾驶舱,起降系统,动力系统这些组件组成,飞机的属性是名字,型号,所属公司,航线等等,飞机的行为包括轰炸,运输货物,起飞,降落等等行为。就跟平常玩象棋的时候,棋子这一类对象,有不同的属性(兵,象,将),就有不同的行为。我对对象的理解就是,假设你在一个学生会,学生会有不同的部门(这叫组件),都有人(对象),有男有女有高有低有胖有瘦(不管有用没用,这是属性),不同部门要合作举办一个活动,有人准备物资,有人准备现场,有人准备宣传,(这是行为)这些对象一起配合完成了活动。

2.熟悉类和对象

2.1 类定义

每个类定义都以关键字class定义和类名开始。类定义是一条C++语句,因此,必须用分号结束。例如:

class SpreadsheetCell

{
public:
void setValue(double inValue);
double getValue() const;
private:
double mValue;

};

2.1.1 类的成员

类可以有许多成员。成员可以使成员函数(方法,构造函数或者析构函数),也可以是成员变量。下面两行声明了类支持的方法:

void setValue(double inValue);
double getValue() const;

下面这行声明了类的数据成员:
double mValue;

类定义了成员函数和数据成员,但是它们只应用于类的特定实例,也就是对象。这个规则的唯一例外就是静态成员(被所有对象共享)。每个对象都会包含自己的mValue变量值。成员函数的实现被所有对象共享,类可以包含任意数量的成员函数和数据成员。

2.1.2 访问控制

类中的每个方法和成员都可以使用三种访问说明符之一来说明:public、protected、private。访问说明符讲应用于其后声明的所有成员,直到遇到另外一个访问说明符。值得注意的是:类的默认访问说明符是private,而struct的默认访问说明符是public。三种访问说明符的具体含义如下所示:



2.2 方法的定义

前面定义了SpreadsheetCell.h,头文件里定义了方法,这就好比是你告诉别人一个机器可以提供加工小麦的服务,但是怎么加工呢?这就需要在方法里面定义。上述类的方法定义如下:

#include"SpreadsheetCell.h"

void SpreadsheetCell::setValue(double invalue)

{
mValue=inValue;

}

double SpreadsheetCell::getValue() const

{
return mValue;

}

::称为作用域解析运算符,在这个环境中,这个语法告诉编译器,要定义的setValue()方法是SpreadsheetCell类的一部分,这个在包含了多个头文件时作用就体现出来了。

2.2.1 访问数据成员

类的非静态方法总是在类的特定对象上执行。在类的方法体中,可以访问对象所属类中的所有数据成员。

无论哪个对象调用这个方法,执行的都是:mValue=inValue。

2.2.2 调用其他方法

当你需要存储不同类型的数据时,你可以不用改变接口,而只需要调用一些方法来实现,对客户来说他看到的界面还是原来的界面只不过功能变多了。

例如,扩展的SpreadsheetCell类:

#ifndef SpreadsheetCell.h

#define SPreadsheetCell.h

class SpreadsheetCell

{
public:
void setValue(double inValue);
double getValue() const;

void setString(const std::string& inString);
const std::string& getString() const;
private:
double mValue;
std::string doubleToString(double inValue) const;
double stringToDouble(const std::string& inString) const;
std::string mString;

};

#endif

这个类的私有访问说明符下面添加了double转换为string和string转换为double的操作,为getvalue和getString服务。

这些方法的具体实现如下:

#include"SpreadsheetCell.h"

#include<iostream>

#include<sstream>

using namespace std;

void SpreadsheetCell::setValue(double inValue)

{
mValue=inValue;
mString = doubleToString(double inValue);

}

double SpreadsheetCell::getValue() const

{
return mValue;

}

void SpreadsheetCell::setString(const string& inString)

{
mString=inString;
mValue=stringToDouble(mstring);

}

const string& SpreadsheetCell::getString() const

{
return mString;

}

string SpreadsheetCell::doubleToString(double inValue) const

{
ostringstream ostr;
ostr<<inValue;
return ostr.str();

}

double SpreadsheetCell::stringToDouble(const string& inString) const

{
double temp;
istringstream istr(inString);
istr>>temp;
if(istr.fail()||!istr.eof())
{
return 0;
}
return temp;

}

2.2.3 this指针

每个普通的方法调用都会传递一个指向对象的指针,这就是称为隐藏的参数this。使用这个指针可以访问数据成员或者调用方法,也可以将其传递给其他方法或者函数。有时还用它来消除名称的歧义。例如,可以使用value而不是mValue作为SpreadsheetCell类的数据成员,用value而不是inValue作为
setValue()方法的参数。

2.2.4 使用对象

创建对象就跟创建int类型的变量一样,只不过你创建的是SpreadsheetCell类型的变量,你会写:

int myNumber;

然后使用myNumber做乘除运算,

你就会写:

SpreadsheetCell mySpreadsheetCell;

然后使用mySpreadsheetCell,只不过使用的时候可能要使用.运算符来使用一些方法。指针的定义也是类似,类定义完使用它而且你又重载了运算符之后,就跟普通的int没什么区别,只不过操作比较多。

对堆或者栈不熟悉可以看(堆和栈的区别

具体来说:

(1)使用堆栈中的对象

SpreadsheetCell myCell,anotherCell;
myCell.setValue(6);
anotherCell.setString("3.14");
cout<<"Cell 1: "<<myCell.getValue()<<endl;
cout<<"Cell 2: "<<anotherCell.getValue()<<endl;

(2)使用堆中的对象

SpreadsheetCell* myCellp=new SpreadsheetCell();
myCellp->setValue(3.7);
cout<<"Cell 1: "<<myCellp->getValue()<<" "<<myCellp->getString()<<endl;
delete myCellp;
myCellp=nullptr;

为了避免忘记释放内存这些操作,可以使用智能指针:

auto myCellp=make_unique<SpreadsheetCell>();
myCellp->setValue(3.7);
cout<<"Cell 1: "<<myCellp->getValue()<<" "<<myCellp->getString()<<endl;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息