学习目的
- 掌握静态数据成员及静态成员函数的使用;
- 掌握友元函数的使用;
- 掌握常成员函数的应用;
- 掌握对象成员的使用;
- 掌握C++11中移动复制构造函数、委托构造函数等语言扩展机制。
实习任务
-
实习任务一
- 调试运行下面的程序,记录程序运行结果
#include <iostream>
#include <string>
using namespace std;
class Mouse{
public:
Mouse( string newName ); ~Mouse();
string getName() {
return name;
}
static int mouseNum;/*static int 不会随着函数的结束而销毁*/
private:
string name;
};
int Mouse::mouseNum = 0;
Mouse::Mouse( string newName ) : name(newName){
cout<<name<<" is born!\n";
mouseNum++;
}
Mouse::~Mouse(){
cout<<name<<" is gone...\n";
mouseNum--;
}
class Cat{
public:
Cat( const string& newName): name(newName){
cout<<name<<" is coming!\n";
}
void catchMouse( Mouse *pMouse);
private:
string name;
};
void Cat::catchMouse( Mouse *pMouse){
cout<<"I catch you! I never want to see you again. "<<pMouse->getName()<<" !"<<endl;
delete pMouse;
}
int main()
{
Cat cat("Black Cat Detective");
Mouse *pMouse1 = new Mouse("Micky");
cout<<Mouse::mouseNum<<" mouse left.\n";
Mouse *pMouse2 = new Mouse("Xiaohua");
cout<<Mouse::mouseNum<<" mouse left.\n";
cat.catchMouse(pMouse2);
cout<<Mouse::mouseNum<<" mouse left.\n";
cat.catchMouse(pMouse1);
cout<<Mouse::mouseNum<<" mouse left.\n";
return 0;
}
static 在main里面的区别不大,其它函数里面区别很大,static变量能保持上次调用后的结果,int在函数返回后就销毁了,下次调用又重新建立。如:
#include <iostream>
void add(){
static int a = 0;
std::cout<<a;
a++;
}
int main()
{
for(int i=0;i<10;i++){
add();
}
return 0;
}
运行结果:0123456789[Finished in 0.3s]
运行结果:
Black Cat Detective is coming!
Micky is born!
1 mouse left.
Xiaohua is born!
2 mouse left.
I catch you! I never want to see you again. Xiaohua !
Xiaohua is gone...
1 mouse left.
I catch you! I never want to see you again. Micky !
Micky is gone...
0 mouse left.
[Finished in 0.3s]
2.调试运行下面的程序,记录程序运行结果
#include <iostream>
using namespace std;
class TestClass{
public:
TestClass( int newValue=0) {
value = newValue;
cout<<"Value: "<<value<<", Constructed!\n";
}
TestClass( const TestClass & rhs){
value = rhs.value;
cout<<"Value: "<<value<<", Copy Constructed!\n";
}
~TestClass() { cout<<"Value: "<<value<<", Destructed!\n"; } void setValue( int newValue) { value = newValue; }
int getValue()const { //常成员函数
return value;
}
private:
int value;
};
TestClass fooFun( TestClass t){
t.setValue(20);
return t;
}
int main(){
TestClass t1(10),t2(t1),t3;
t3=fooFun(t1);
return 0;
}
运行结果
Value: 10, Constructed!
Value: 10, Copy Constructed!
Value: 0, Constructed!
Value: 10, Copy Constructed!
Value: 20, Copy Constructed!
Value: 20, Destructed!
Value: 20, Destructed!
Value: 20, Destructed!
Value: 10, Destructed!
Value: 10, Destructed!
[Finished in 0.3s]
- 将程序1中的fooFun传递对象作为参数和返回对象修改为传递引用以及返回引用,重新运行程序,记录运行结果。
TestClass & fooFun(TestClass &t){
t.setValue(20);
return t;
}
运行结果:
Value: 10, Constructed!
Value: 10, Copy Constructed!
Value: 0, Constructed!
Value: 20, Destructed!
Value: 10, Destructed!
Value: 20, Destructed!
[Finished in 0.5s]
-
实习任务二
实习 2 中的分数类还很不完善,请按照下面定义和要求完善分数类。
- 将 Complex 类中的 getDoubleValue、getNum、getDen、output 定义为常成员函数。将构造函数的实现写成初始化列表的形式。
- 添加常成员函数 add,实现复数相加计算,计算结果返回一个新的复数对象,为Complex类型。
- 添加成员函数 multiply,实现当前复数的向量放大计算,实部和虚部同时放大,返回类型为 void。
常成员函数是指由const修饰符修饰的成员函数,在常成员函数中不得修改类中的任何数据成员的值。
#include <iostream>
#include <cmath>
using namespace std;
class Complex{
public:
// Complex(){
// real = 0;
// image = 0;
// }
// Complex(double n){
// real = n;
// image = 0;
// }
Complex(double n=0, double d=0){
real = n;
image = d;
}
void setValue(double n, double d){
real = n;
image = d;
}
Complex add(const Complex &c )const{
Complex x;
x.setValue(real+c.getReal(), image+c.getImage());
return x;
}
double getReal()const{
return real;
}
double getImage()const{
return image;
}
double getDistance()const{
return sqrt(pow(real,2)-pow(image,2));
}
void multiply(double c){
setValue(real*c, image*c);
}
void output()const{
if(image == 0 && real != 0){
cout<<real<<endl;
}
else if(image !=0 && real ==0){
cout<<image<<'i'<<endl;
}
else if(image == 0 && real == 0){
cout<<0<<endl;
}
else{
if(image<0){
cout<<real<<image<<'i'<<endl;
}
else{
cout<<real<<'+'<<image<<'i'<<endl;
}
}
}
private:
double real;
double image;
};
int main(){
Complex c1, c2(2), c3(3,4);
c1.output();
c2.output();
c3.output();
c3.multiply(3);
c3.output();
c2.add(c3).output();
c1.setValue(6,4);
c1.output();
cout<<c1.getDistance()<<endl;
return 0;
}
运行结果:
0
2
3+4i
9+12i
11+12i
6+4i
4.47214
[Finished in 0.3s]
-
实习任务三
- 完善实习2中的Time类
#include <iostream>
#include <cmath>
using namespace std;
class Time{
public:
Time(){
hour = 0;
minute = 0;
normalizeTime();
}
Time(int h, int m){
hour = h;
minute = m;
normalizeTime();
}
Time(int minutes){
hour = (minutes/60)%24;
minute = minutes%60;
normalizeTime();
}
void setTime(int h, int m){
hour = h;
minute = m;
normalizeTime();
}
void output()const{
cout<<hour<<':'<<minute<<endl;
}
int getHour()const{
return hour;
}
int getMinute()const{
return minute;
}
int getTotalMinutes()const{
return hour*60 + minute;
}
Time getTimeSpan(const Time &t)const{
Time x;
int dis = abs(getTotalMinutes() - t.getTotalMinutes());
x.setTime((dis/60)%24, dis%60);
return x;
}
private:
int hour;
int minute;
void normalizeTime(){
hour = ((60*hour + minute)/60)%24;
minute = minute%60;
}
};
int main(){
Time t1(12, 75);
t1.output();
t1.setTime(8, 65);
t1.output();
Time t2(12, 13);
t1.getTimeSpan(t2).output();
cout<<"t1 Hour:"<<t1.getHour()<<endl;
cout<<"t1 Minute:"<<t1.getMinute()<<endl;
cout<<"t1 getTotalMinutes:"<<t1.getTotalMinutes()<<endl;
return 0;
}
运行结果:
13:15
9:5
3:8
t1 Hour:9
t1 Minute:5
t1 getTotalMinutes:545
[Finished in 0.3s]
- 停车收费问题
class ParkingCard{
public:
ParkingCard(double newRate){
rate = newRate;
}
void setRate(double newRate){
rate = newRate;
}
double getRate()const{
return rate;
}
void setParkingTime(const Time &time){
parkingTime.setTime(time.getHour(), time.getMinute());
}
void setLeavingTime(const Time &time){
leavingTime.setTime(time.getHour(), time.getMinute());
}
double getTotalExpenses()const{
Time x = parkingTime.getTimeSpan(leavingTime);
return x.getTotalMinutes()*(rate/60.0);
}
void output()const{
cout<<"Your parking time: ";
parkingTime.output();
cout<<"Our parking rate: ";
cout<<rate<<endl;
cout<<"Your total expenses: ";
cout<<getTotalExpenses()<<endl<<endl;
}
private:
double rate;
Time parkingTime;
Time leavingTime;
};
int main(){
ParkingCard card(5);
card.setParkingTime(Time(9,20));
card.setLeavingTime(Time(11,35));
cout<<"Expenses:"<<card.getTotalExpenses()<<endl;
cout<<"Detailed info:\n";
card.output();
return 0;
}
运行结果:
Expenses:11.25
Detailed info:
Your parking time: 9:20
Our parking rate: 5
Your total expenses: 11.25
[Finished in 0.3s]
-
实习任务四
- Point 类?
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point():x(0), y(0){}//初始化列表
Point(double newX, double newY){
setValue(newX, newY);
}
Point(const Point &p){
setValue(p.getX(), p.getY());
}
//~Point();
void setValue(double newX, double newY){
x = newX;
y = newY;
}
double getX()const{return x;}
double getY()const{return y;}
double getDistance(const Point &p2)const{
return sqrt(pow(x-p2.getX(),2)+pow(y-p2.getY(),2));
}
friend double getDistance(const Point &p1, const Point &p2){
return sqrt(pow(p1.getX()-p2.getX(),2)+pow(p1.getY()-p2.getY(),2));
}//友元函数
private:
double x,y;
};
int main()
{
Point p1(3,4);
Point p2(5,2);
double distance = p1.getDistance(p2);
cout<<"Distance:"<<distance<<endl;
distance = getDistance(p1,p2);
cout<<"Distance:"<<distance<<endl;
return 0;
}
运行结果:
Distance:2.82843
Distance:2.82843
[Finished in 0.4s]
- 三角形类
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point():x(0), y(0){}//初始化列表
Point(double newX, double newY){
setValue(newX, newY);
}
Point(const Point &p){
setValue(p.getX(), p.getY());
}
~Point(){}
void setValue(double newX, double newY){
x = newX;
y = newY;
}
double getX()const{return x;}
double getY()const{return y;}
double getDistance(const Point &p2)const{
return sqrt(pow(x-p2.getX(),2)+pow(y-p2.getY(),2));
}
friend double getDistance(const Point &p1, const Point &p2){
return sqrt(pow(p1.getX()-p2.getX(),2)+pow(p1.getY()-p2.getY(),2));
}//友元函数
private:
double x,y;
};
class Triangle{
public:
Triangle(const Point &p1, const Point &p2, const Point &p3){
this->p1 = p1;
this->p2 = p2;
this->p3 = p3;
}
double getArea()const{
return abs((1/2.0)*(p1.getX()*p2.getY()-p1.getY()*p3.getX()-p1.getY()*p2.getX()*p3.getY()+p3.getX()*p2.getY()+p1.getX()*p3.getY()+p2.getX()*p1.getY()));
}
double getPerimeter()const{
return getDistance(p1,p2)+getDistance(p2,p3)+getDistance(p1,p3);
}
private:
Point p1, p2, p3;
};
int main()
{
Point p1(0,0), p2(0,3), p3(4,0);
Triangle t(p1, p2, p3);
cout<<"Area:"<<t.getArea()<<endl;
cout<<"Perimeter:"<<t.getPerimeter()<<endl;
return 0;
}
运行结果:
Area:6
Perimeter:12
[Finished in 0.3s]
-
课后练习
#include <iostream>
using namespace std;
class Example{
private:
int i;
public:
Example(int n) {
i=n;
cout<<"Constructing. "<<endl;
}
~Example() {
cout<<"Destructing. "<<endl;
}
int get_i() {
return i;
}
};
int sqrt_it(Example o) {
return o.get_i()*o.get_i();
}
int main()
{
Example x(10);
cout<<x. get_i()<<endl;
cout<<sqrt_it(x)<<endl;
return 0;
}
运行结果:
Distance:2.82843
Distance:2.82843
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Test{
public:
Test() {
cout<<"Default constructor."<<endl;
}
Test(const Test& t){
cout<<"Copy constructor!"<<endl;
}
};
void fun(Test p) {}
int main(){
Test a;
fun(a);
return 0;
}
运行结果:
Default constructor.
Copy constructor!
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Dog{
public:
static int number;
Dog(){
number++;
cout<<"New Dog"<<endl;
}
~Dog(){
number--;
cout<<"A Dog Die"<<endl;
}
};
int Dog::number=0;
int main(){
Dog dog;
Dog *pDog=new Dog();
delete pDog;
cout<<Dog::number<<endl;
return 0;
}
运行结果:
New Dog
New Dog
A Dog Die
1
A Dog Die
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Test{
public:
Test(int xx=1):x(xx){}
void output()const{cout<<"x:"<<x<<endl;
}
private:
int x;
};
int main()
{
Test t;
t.output();
t=4; //尽量不要这么写!
t.output();
return 0;
}
运行结果:
x:1
x:4
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Test{
public:
Test(){
cout<<"Default Constructor\n";
}
Test(int xx):x(xx){
cout<<"Int Constructor\n";
}
Test(const Test& t):x(t.x){//直接使用t的私有变量
cout<<"Copy Constructor\n";
}
private:
int x;
};
Test t;
int main(){
cout<<"--------------------\n"; Test tt(t);
return 0;
}
运行结果:
Default Constructor
--------------------
Copy Constructor
[Finished in 0.3s]
- 不标明private,默认private?
#include <iostream>
using namespace std;
class Point {
int x,y;
public:
Point(int x1=0, int y1=0):x(x1), y(y1) {
cout<<"Point:"<<x<<' '<<y<<'\n';
}
~Point() {
cout<<"Point destructor!\n"; }
};
class Circle {
Point center;//圆心位置
int radius;//半径
//私有!
public:
Circle(int cx,int cy, int r):center(cx,cy),radius(r) {
cout<<"Circle radius:"<<radius<<'\n';
}
~Circle() {
cout<<"Circle destructor!\n";
}
};
int main(){
Circle c(3,4,5);
return 0;
}
运行结果:
Point:3 4
Circle radius:5
Circle destructor!
Point destructor!
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Test{
public:
Test(){
cout<<"Hello: "<<++i<<endl;
}
static int i;
};
int Test::i=0;
int main(){
Test t[2];
Test *p;
p=new Test[2];
return 0;
}
运行结果:
Hello: 1
Hello: 2
Hello: 3
Hello: 4
[Finished in 0.3s]
#include <iostream>
#include <string>
using namespace std;
class Person{
private:
string name;
int age;
public:
Person(string name,int age);
~Person(){
cout<<"Bye! My name is "<<name<<", I'm "<<age<<" years old."<<endl;
}
void growup(){
age++;
}
};
Person::Person(string name, int age){
this->name = name;
this->age = age;
cout<<"Hello,"<<name<<" is comming!"<<endl;
}
int main(){
Person p("zhang",1);
for(int i=0;i<90;++i)
p.growup();
return 0;
}
运行结果:
Hello,zhang is comming!
Bye! My name is zhang, I'm 91 years old.
[Finished in 0.3s]
- 下面的程序无法通过编译,分析原因并出修改办法。
#include <iostream>
#include <vector>
class Test{
private:
int a;
public:
Test(const Test& t)=default;
};
int main(){
Test t;
return 0;
}
本来编译器会给类默认添加一个Test(){},如果使用过了“default”,编译器就不会再添加。把public下的Test(cosnt Test &t) = default注释掉,或者在前添加Test(){}就可通过编译。
#include <iostream>
using namespace std;
class Test{
private:
int a,b;
public:
Test():Test(1){
cout<<"Constructor without parameter!\n";
}
Test(int x):Test(x,10){
cout<<"Constructor with 1 parameter!\n";
}
Test(int x,int y):a(x),b(y){
cout<<"Constructor with 2 paramter!\n";
}
void output()const{
cout<<a<<","<<b<<endl;
}
};
int main(){
Test t;
t.output();
Test t1(3,5);
t1.output();
return 0;
}
运行结果:
Constructor with 2 paramter!
Constructor with 1 parameter!
Constructor without parameter!
1,10
Constructor with 2 paramter!
3,5
Program ended with exit code: 0
#include <iostream>
using namespace std;
class Test{
private:
int a;
public:
Test(){
cout<<"Default constructor!\n";
}
Test(int x):a(x){
cout<<"Constructor!\n";
}
Test(const Test& t){
a=t.a;
cout<<"Copy constructor!\n";
}
Test(Test && t){
a=t.a;
cout<<"move copy constructor!\n";
}
};
Test fun(){
return Test(3);
}
int main(){
Test t;
Test t2=move(fun());
return 0;
}
运行结果:
Default constructor!
Constructor!
move copy constructor!
Program ended with exit code: 0
#include <iostream>
#include <vector>
using namespace std;
class Element{
private:
int a;
public:
Element(int e=0):a(e){}
Element(const Element& e):Element(e.a){
cout<<"Copy constructor!\n";} Element(Element&& e):Element(e.a){cout<<"Move copy constructor!\n";
}
};
int main(){
vector<Element> vec;
vec.reserve(10);
vec.push_back(Element(3));
Element e(5);
vec.push_back(e);
return 0;
}
运行结果:
Move copy constructor!
Copy constructor!
Program ended with exit code: 0