类编写的前情回顾以及项目实战(1)

在开始类的编写之前我们依然需要回顾整理一下前面所说的内容,(前面虽然是一个自定义数据类型的实现过程,但是内容有点繁杂).

先看一段代码:

/** @file calssStruct.cpp *//** Member Functions for Class point */#include <cmath> // for sqrt and atanusing namespace std;struct point{ point() : x_(0.0), y_(0.0) {} point(double x, double y) : x_(x), y_(y) {} point(point const& pt) : x_(pt.x_), y_(pt.y_) {} /// Distance to the origin. double distance() {return std::sqrt(x*x + y*y); } /// Angle relative to x-axis. double angle() {return std::atan2(y, x); } /// Add an offset to x and y. void offset(double off) {offset(off, off); } /// Add an offset to x and an offset to y void offset(double xoff, double yoff) {x = x + xoff;y = y + yoff; } /// Scale x and y. void scale(double mult) {this->scale(mult, mult); } /// Scale x and y. void scale(double xmult, double ymult) {this->x = this->x * xmult;this->y = this->y * ymult; } double x_; double y_;};

上面代码中有构造函数,有成员函数,有数据成员.我们现在需要分析一个在上面和之前的成员函数中出现的一个this引用.

在C++中,每个成员函数都有一个隐含的形参this,当成员函数被调用时,其对象本身就被编译器作为实参隐式传入.在成员函数中可以使用*this表达式访问该对象.在C++语法中点操作符比星操作符优先级高,因此需要使用圆括号(如(*this).x).另一种等价的调用时使用”箭头”,即是this->x.

但是其实编译器可以自动识别那些是成员名字,所以this->是可选的,即是可以省略的.但是有时候为了代码清晰总是加上它.而一些程序员则为了表明是数据成员,有时候往往在数据成员名称前面加上前缀,或者在后面加上后缀.我倾向于后缀,如上面的代码.

关于构造函数,初始化时类和内置类型的一个重要区别,如果定义一个内置类型而不提供初始化序列,那么它的值就是无意义的;而定义类的对象时,该对象一定会被构造器初始化,因此总有机会初始化数据成员.

尽管构造函数的冒号后面的初始化列表是可选的,但是建议总是加上.

根据数据成员的类型是类或者内置类型,编译器会做出不同的处理.每个成员的初始化表有下面的三种情况:

下面再来一个构造函数的验证代码:

/** @file constructFun.cpp *//** Visual Constructors */#include <iostream>#include <ostream>using namespace std;struct demo{ demo(): x_(0) { std::cout << "default constructor\n"; } demo(int x) : x_(x) { std::cout << "constructor(" << x << ")\n"; } demo(demo const& that) : x_(that.x_) {std::cout << "copy constructor(" << x_ << ")\n"; } int x_;};demo addone(demo d){ ++d.x_; return d;}int main(){ demo d1; demo d2(d1); demo d3(42); demo d4(addone(d3));}

结果如下:

但是是否是学习到这里我们就把构造函数什么的搞明白了呢,下面我们来测试一下,先看代码:

/** @file Test_Construct.cpp *//** Mystery Program */#include <iostream>#include <ostream>using namespace std;struct point{ point() : x_(0.0), y_(0.0) {cout << "default constructor\n"; } point(double x, double y) : x_(x), y_(y) {cout << "constructor(" << x << ", " << y << ")\n"; } double x_; double y_;};int main(){ point pt();}

你认为这个编译后会输出什么呢?是default constructor么?

但是你错了……这就是输出:

即是根本没有定义变量,编译器认为你编写了一个无参数的返回值为point的名字是pt的函数声明!

如果你不理解那么把point改成int,现在是intpt();这样是不是就更像一个函数声明了呢.但是如果要定义一个变量应该怎么样的呢?

是 point pt;即是不带括号这个时候调用了默认的无参数构造函数初始化.

所以在定义变量的时候注意哪些括号是必须的,不然很可能就会误导编译器将你的所谓的”变量声明”当成函数声明.

练习项目一

身体质量指数BMI小程序

学习了那么多可以做个小项目练习一下了.要计算BMI需要知道一个人的身高体重,BMI的计算公式是体重/(身高^2),结果是一个无单位的值.现在的任务是编写一个程序,使其能够读取记录,打印记录并计算一些统计值.该程序以请求一个BMI上极限开始,仅打印BMI值大雨或等于此极限值的记录,每条记录包含姓名(可以有空格),体重,身高(单位cm),以及性别(M或F,不限大小写).读取完每个人的记录后要立即打印该记录的BMI值,手机所有的记录后,基于数据打印两个表——男性一个,女性一个.在BMI值后面用*标记超过界限的BMI记录.并打印BMI的均值和中值.

躲在墙角、掩藏那孤独而又不奢怜悯的伤…

类编写的前情回顾以及项目实战(1)

相关文章:

你感兴趣的文章:

标签云: