C++ 静态成员与友元 练习

实验目的

掌握拷贝构造函数和赋值运算符的使用方法

掌握静态成员变量和静态成员函数的使用方法

了解C++友元机制和掌握友元的使用方法

实验内容

(重点掌握)给出学生类的声明如下:

class Student  

{  

public:  

    enum Gender { Male,  Female }; //枚举类型,性别

    //声明友元函数,用于将枚举类型输出文本形式  

    friend std::ostream& operator<<(std::ostream& os, Gender gender);  

    Student(); //无参数构造函数  

    Student(const char* name, Gender gender); //带参数构造函数  

    Student(const Student& student); //拷贝构造函数  

    Student& operator= (const Student& student); //赋值运算符  

    ~Student(); //析构函数,释放内存 

    void Show() const; //常成员函数用于显示学生姓名和性别  

private:  

    char* name_;    //名字  

    Gender gender_; //性别  

};  

完成学生类的实现,并利用下面给出的main函数测试所有的成员函数。(可以尝试在常成员函数中修改成员数据,观察编译器是否报错)。

int main()  

{  

    Student s1;  

    Student s2("Nicolas ZhaoSi", Student::Gender::Male);  

    Student s3("Jason GuoDa Statham", Student::Gender::Male);  

    Student s4(s2);  

    s1 = s3;  

    s1.Show();  

    s2.Show();  

    s3.Show();  

    s4.Show();  

}  

声明一个Student类,在该类中包含一个数据成员表示学生成绩、两个静态数据成员表示总成绩和学生人数;有参构造函数用于设置成绩、累计成绩之和、累计学生人数,一个静态函数用于返回学生的成绩之和,另一个静态成员函数用于取全部成绩的平均分。在main函数中输入某班同学的成绩,并调用上述函数求出全部学生的成绩之和和平均分。


class Student  

{  

  public:  

    Student(){}

Student(double score);  //设置成绩  

    static double Sum();        //返回成绩总和  

    static double Average();    //求平均成绩  

  private:    

    int score_;               //成绩  

    static double total_score_;   //总成绩  

    static double total_numbers_;  //学生人数  

}  

  

int main()  

{  

  int n; //学生总数  

  cin >> n; //键盘输入学生总数 

  

  //根据输入的学生人数创建学生数组  

  //可以从键盘输入学生成绩,也可以随机生成。  

  

  return 0;  

}  

(重点掌握)定义一个平面点的类Point,其中x和y坐标设为私有数据成员。定义线段类Line,数据成员包括线段的两个端点、线段的长度,定义线段类Line的常成员函数用于显示线段端点坐标和线段长度。完成两个类的构造函数和一些必要的成员函数,并在main函数中构建两条线段,调用常成员函数显示结果。

class Point  

{  

public:  

    Point(); //无参构造函数  

    Point(int x, int y); //有参构造函数  

    int get_x() const; //返回x坐标  

    int get_y() const; //返回y坐标  

    double Distance(const Point& point);//计算到当前点到点point的距离

   //重载输出运算符,格式化输出点(x,y) 

    friend ostream& operator<<(ostream& os, const Point& point); 

      

private:  

    int x_;  

    int y_;  

};  

class Line  

{  

public:  

    Line();//无参构造函数  

    Line(int x1, int y1, int x2, int y2); //(x1,y1)和(x2,y2)两个点构造线段  

    Line(Point& p1, Point& p2);//p1和p2两个点构造线段  

    double Length() const; //返回线段长度  

    void Show() const; //显示线段的两个端点以及线段长度  

  

private:  

    Point start_point_;  

    Point end_point_;  

    double length_;  

};  

int main()  

{  

  Point p1(1, 1);  

Point p2(2, 2);  

Line line1(p1, p2);  

Line line2(1, 2, 3, 4);  

line1.Show();  

line2.Show();  

}  

代码

作业1

第一个在vs里会报错,析构函数那里注释掉就能运行了,clion就没问题
dev里删掉:Gender:就行

#define _CRT_SECURE_NO_DEPRECATE
#include<string.h>
#include<iostream>
using namespace std;
class Student {
public:
    enum Gender { Male, Female }; //枚举类型,性别
    //声明友元函数,用于将枚举类型输出文本形式
    friend std::ostream& operator<<(std::ostream& os, Gender gender);
    Student();//无参数构造函数
    Student(const char* name, Gender gender);//带参数构造函数
    Student(const Student& student); //拷贝构造函数
    Student& operator= (const Student& student); //赋值运算符
    ~Student(); //析构函数,释放内存
    void Show() const;//常成员函数用于显示学生姓名和性别
private:
    char* name_;    //名字
    Gender gender_; //性别
};
std::ostream& operator<<(std::ostream& os, Student::Gender gender)
{
    if (gender == 0) {
        return os << "Male" << endl;
    }
    else {
        return os << "Female" << endl;
    }
}
Student::Student()
{
    this->name_ = NULL;
    this->gender_ = Male;
}
Student::Student(const char* name, Gender gender)//带参数构造函数
{
    this->name_ = new char[strlen(name) + 10];
    strcpy(name_, name);
    this->gender_ = gender;
}
Student::Student(const Student& student) //拷贝构造函数
{
    this->name_ = new char[strlen(student.name_) + 10];
    strcpy(this->name_, student.name_);
    this->gender_ = student.gender_;
}
Student& Student::operator = (const Student& student) //赋值运算符
{
    this->name_ = student.name_;
    this->gender_ = student.gender_;
    return *this;
}
Student::~Student() //析构函数,释放内存
{
    delete[] name_;
    delete[] & gender_;
}
void Student::Show() const//常成员函数用于显示学生姓名和性别
{
    cout << this->name_ << endl;
    cout << this->gender_ << endl;
}
int main()
{
    Student s1;
    Student s2("Nicolas ZhaoSi", Student::Gender::Male);
    Student s3("Jason GuoDa Statham", Student::Gender::Male);
    Student s4(s2);
    s1 = s3;
    s1.Show();
    s2.Show();
    s3.Show();
    s4.Show();
    return 0;
}

作业1改进

这串代码在clion和vs里面都不会报错
问题出现在析构函数和操作符重载那里,析构函数没有判断原来就是NULL的情况,操作符重载那里是忘记用new动态开辟空间了…(太粗心了~_~)
不得不说,vs的严格程度还是比clion高很多的,但是clion的警告倒是一堆
如果dev要运行,还是要删掉:Gender:

#define _CRT_SECURE_NO_DEPRECATE
#include<string.h>
#include<iostream>
using namespace std;
class Student {
public:
    enum Gender { Male, Female }; //枚举类型,性别
    //声明友元函数,用于将枚举类型输出文本形式
    friend std::ostream& operator<<(std::ostream& os, Gender gender);
    Student();//无参数构造函数
    Student(const char* name, Gender gender);//带参数构造函数
    Student(const Student& student); //拷贝构造函数
    Student& operator= (const Student& student); //赋值运算符
    ~Student(); //析构函数,释放内存
    void Show() const;//常成员函数用于显示学生姓名和性别
private:
    char* name_;    //名字
    Gender gender_; //性别
};
std::ostream& operator<<(std::ostream& os, Student::Gender gender)
{
    if (gender == 0) {
        return os << "Male" << endl;
    }
    else {
        return os << "Female" << endl;
    }
}
Student::Student()
{
    this->name_ = NULL;
    this->gender_ = Male;
}
Student::Student(const char* name, Gender gender)//带参数构造函数
{
    this->name_ = new char[strlen(name) + 10];
    strcpy(this->name_, name);
    this->gender_ = gender;
}
Student::Student(const Student& student) //拷贝构造函数
{
    this->name_ = new char[strlen(student.name_) + 10];
    strcpy(this->name_, student.name_);
    this->gender_ = student.gender_;
}
Student& Student::operator = (const Student& student) //赋值运算符
{
//    if (this == &student)//判断是不是它本身,是的话返回this
//        return *this;
//    if (this->name_ != NULL){//vs有没有这仨都不会报错,但是加上比较好
//        delete this->name_;
//    }
//    if (this->gender_ != NULL){
//        delete &this->gender_;
//    }

    this->name_ = new char [strlen(student.name_) + 10];//记住要开辟空间
    strcpy(this->name_,student.name_);
    this->gender_ = student.gender_;
    return *this;
}
Student::~Student() //析构函数,释放内存
{
    if (name_!=NULL){//需要考虑空间本来就是null的情况,不然vs会出现异常
        delete[] name_;
        name_ = NULL;
    }
    if (gender_ != NULL){
        delete[] & gender_;
        gender_ = static_cast<Gender>(NULL);
    }
}
void Student::Show() const//常成员函数用于显示学生姓名和性别
{
    cout << this->name_ << endl;
    cout << this->gender_ << endl;
}
int main()
{
    Student s1;
    Student s2("Nicolas ZhaoSi", Student::Gender::Male);
    Student s3("Jason GuoDa Statham", Student::Gender::Male);
    Student s4(s2);
    s1 = s3;
    s1.Show();
    s2.Show();
    s3.Show();
    s4.Show();
}

作业2

#define _CRT_SECURE_NO_DEPRECATE

#include<iostream>

using namespace std;

class Student {

public:

    Student() {}

    Student(double score);

    Student(int score);

    static double Sum();        //返回成绩总和

    static double Average();    //求平均成绩

private:

    int score_;               //成绩

    static double total_score_;   //总成绩

    static double total_numbers_;  //学生人数

};
double Student::total_score_ = 0;
double Student::total_numbers_ = 0;

Student::Student(double score) {
    this->score_ = score;
    total_score_ += score;
    total_numbers_++;
}

Student::Student(int score) {
    this->score_ = score;
    total_score_ += score;
    total_numbers_++;
}

double Student::Sum()        //返回成绩总和
{
    return total_score_;
}

double Student::Average()    //求平均成绩
{
    return total_score_ / total_numbers_;
}
Student* student[1000000];//创建对象数组
int main() {
    int n; //学生总数
    cin >> n; //键盘输入学生总数
    for (int i = 0; i < n; ++i) {
        double a = rand() % 101;
        student[i] = new Student(a);
    }

    cout << Student::Average() << endl;
    cout << Student::Sum() << endl;


    return 0;

}

作业3

#define _CRT_SECURE_NO_DEPRECATE

#include<iostream>
#include <math.h>

using namespace std;

class Point {
public:
    Point(); //无参构造函数
    Point(int x, int y); //有参构造函数
    int get_x() const; //返回x坐标
    int get_y() const; //返回y坐标
    double Distance(const Point& point);//计算到当前点到点point的距离
    //重载输出运算符,格式化输出点(x,y)
    friend ostream& operator<<(ostream& os, const Point& point);
private:
    int x_;
    int y_;
};
Point::Point() //无参构造函数
{
    x_ = 0;
    y_ = 0;
}
Point::Point(int x, int y) //有参构造函数
{
    x_ = x;
    y_ = y;
}
int Point::get_x() const //返回x坐标
{
    return x_;
}
int Point::get_y() const //返回y坐标
{
    return y_;
}
double Point::Distance(const Point& point) //计算到当前点到点point的距离
{
    return sqrt(pow((point.get_x() - this->x_), 2) + pow((point.get_y() - this->y_), 2));
}
//重载输出运算符,格式化输出点(x,y)
ostream& operator<<(ostream& os, const Point& point)
{
    return os << "x:" << point.x_ << " " << "y:" << point.y_;
}

class Line {
public:
    Line();//无参构造函数
    Line(int x1, int y1, int x2, int y2); //(x1,y1)和(x2,y2)两个点构造线段
    Line(Point& p1, Point& p2);//p1和p2两个点构造线段
    double Length() const; //返回线段长度
    void Show() const; //显示线段的两个端点以及线段长度
private:
    Point start_point_;
    Point end_point_;
    double length_;
};
Line::Line()//无参构造函数
{
    start_point_ = Point(0, 0);
    end_point_ = Point(0, 0);
    length_ = Length();
}
Line::Line(Point& p1, Point& p2)//p1和p2两个点构造线段
{
    this->start_point_ = p1;
    this->end_point_ = p2;
    this->length_ = start_point_.Distance(end_point_);
}
Line::Line(int x1, int y1, int x2, int y2) //(x1,y1)和(x2,y2)两个点构造线段
{
    Point p1 = Point(x1, y1);
    Point p2 = Point(x2, y2);
    this->start_point_ = p1;
    this->end_point_ = p2;
    this->length_ = start_point_.Distance(end_point_);
}
double Line::Length() const //返回线段长度
{
    return this->length_;
}
void Line::Show() const //显示线段的两个端点以及线段长度
{
    cout << this->start_point_ << endl;
    cout << this->end_point_ << endl;
    cout << this->length_ << endl;
}
int main() {
    Point p1(1, 1);
    Point p2(2, 2);
    Line line1(p1, p2);
    Line line2(1, 2, 3, 4);
    line1.Show();
    line2.Show();
}

参考:
C++拷贝构造函数详解
一文说尽C++赋值运算符重载函数(operator=)//这位大佬讲的很全
C++静态成员变量与静态成员函数

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值