以下是几点学习C++后续内容的体会和注意之处,更新ing…………
对于类的几点认识:
---------《以下的几条规范是便于多文件管理,分别编译的》---------
1.将类的声明放在h文件中,注意是声明,而不是定义,命名之,最好用类

名来给这个h文件命名。
2.将类的定义放在cpp文件中,单独一个cpp文件中,以类名命名之。
3.将主函数放在单独一个文件cpp中,文件名无所谓,不过取main的话便于

找到主体程序在哪里。

下面要说的是虚函数:virtual
1.在类中要声明virtual,但是放在对应的定义cpp文件中的时候,要注意去

掉virtual,否则会报错。
2.注意声明和定义的原型都必须完全一样,比如声明中有一个const,那么

在定义中必须也要有,否则的话就会报错,说不认识这个函数。
3.在类外定义的话一定要加上类型限定符,作用域限定符。

下面写点代码:
student.h头文件
1
#ifndef STUDENT_H
2
#define STUDENT_H
3
4
#include <iostream>
5
using std::string;
6
7
8
class Student
9

{
10
public:
11
Student(const string& a="",double b=0.0,int c=0):score(b),name(a),number(c)
12
{}
13
~Student()
{}
14
//void show_score();
15
//void modify(Student& a);
16
friend Student operator+(Student& a,Student& b);
17
friend Student operator-(Student& a,Student& b);
18
friend std::ostream& operator<<(std::ostream &a,Student& b); //改变状态的一般都要定义为类成员,++,--及*
19
friend std::istream& operator>>(std::istream &a,Student& b);//进行算术运算和输入输出的就定义为友元
20
//Student& operator=(Student& a);
21
private:
22
double score;
23
string name;
24
int number;
25
};
26
27
#endif
1
student.cpp文件,实现类函数
2
#include <iostream>
3
#include <string>
4
#include "Student.h"
5
using std::cout;
6
using std::cin;
7
using std::endl;
8
9
Student operator+(Student& a,Student& b) //这里面又用到了<<这个运算符的。而这个你已经自定义了啊!
10

{
11
cout << a.name << "和" << b.name << "分数之和为:" << a.score+ b.score;
12
cout << endl;
13
return a;
14
}
15
Student operator-(Student& a,Student& b)
16

{
17
cout << a.name << " 比 " << b.name << "多" <<
18
(a.score > b.score)?(a.score-b.score):(b.score - a.score);
19
cout << endl;
20
return a;
21
}
22
std::ostream& operator<<(std::ostream &a,Student& b)
23

{
24
a << b.name<<"的分数:" << b.score << "\t 学号:" << b.number << endl;
25
return a;
26
}
27
std::istream& operator>>(std::istream &a,Student& b)
28

{
29
a >> b.name >>b.number >> b.score ;
30
return a;
31
}
32
/**//*
33
问题1,修改定义函数的时候没有修改声明,为什么这么粗心呢?
34
2.返回值,特别是对于有输入输出流的,要有返回值啊!
35
3.流的返回值和调用。
36
4.返回值怎么能为void呢?因为要输出a+b,所以要返回一个值啊,相当于opreator+(a,b)
37
*/
主函数:main.cpp
1
#include <iostream>
2
#include "Student.h"
3
4
using namespace std;
5
6
int main()
7

{
8
Student a,b;
9
cout << "依次输入姓名,学号,成绩" << endl;
10
cin >> a >> b;
11
cout << a << b;
12
cout << endl;
13
return 0;
14
}
15
我想说的是自己遇到的几个问题:
1.重载<< 和>>操作符:这两个操作符只能作为友元而不是成员函数。作为重载运算符,有两种定义形式,即:成员函数形式和非成员函数形式,对于成员函数的形式,它的声明方式是形参数要比操作数少一个,为什么呢,因为省略了默认的形参this指针,而这个省略的形参正式左操作数,即定义这样的运算符的时候,this指针指向的是左操作数。其次,就是非成员函数,即友元声明方式。友元声明方式较简单合理,形参数和操作数相同,显示的是合理的调用函数的方式。
2.什么时候用成员函数的声明方式,什么时候用友元函数的声明方式?此部分需注意的是:1,对于=,(),【】,->这四个操作符只能作为成员函数来声明,想想这个是为什么呢?
(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(2)单目运算符最好重载为成员函数。
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
关于此问题的详细讨论,见:http://www.rupeng.com/forum/thread-4468-1-1-uid3573.html
在C++编程思想中有述,据网友而言,大意是:如果可以定义为全局变量的话,那么就可以定义为int operator =(int,mytype),而这种方式的话就不对了,因为赋值=是和左边的类紧密相连的,所以会定义为成员函数的……
此部分详细关注中………………
3.关于重载运算符的返回值的问题:
我们是不是已经习惯于重载运算符有一个返回值类型呢?对,是的,我们经常这么干,现在的问题是,如果我定义为void的话,会出错吗?
不会的,将上面的换成void的返回值照样不会出错!
为什么呢?因为定义有返回值只是我们的一个习惯,为何有返回值,因为我们要返回值,很白痴吧?可是事实就是这样,想想这个:
cout << a + b; 这个代码很简单是吧,a+b 实际上就是operator+(a,b)的一个等价形式,我要能够cout ,那么必然有一个返回值,否则的话调用这个函数没有返回值的话我怎么cout它呢?于是乎我们在定义加法的重载的时候就只能在前面加上a和b的类型了。
好,现在我没有类型了,void,怎么办?很简单,直接用 a + b; 因为它相当于:operator+(a,b);也就是调用一个函数,直接调用,没有返回值。
当然,结果也还是对的,各位可以看看…………
注意我想说的,学习计算机主要的是学习那个思想,而不是片面的记住语法或者其他,要想想为什么需要这样,这样我们的思维才会和计算机接近,才能更好的理解计算机,上面的这个例子就是很好的说明,这个函数很另类了吧,可是它完全符合各种语法,能够顺利运行。。
可是要记住的是,重载运算符为什么要重载,就是为了使用和内置类型一样的自然,如果像上面我定义的void那样,那么恐怕就很难懂了,如果将减号定义为加法的话,那么就更加的匪夷所思。也很难读了,违背了初衷,也就是一种错误的做法了,虽然理论上是可行的。。
计算机是一个很奇妙的东西,需要我们用心去体会……
------------------------------<本章完>
posted on 2009-09-28 21:36
deercoder 阅读(594)
评论(0) 编辑 收藏 引用 所属分类:
C/C++