实验二
task.cpp
1 #include"T.h" 2 #include<iostream> 3 void test_T(); 4 int main() { 5 std::cout << "test Class T:\n"; 6 test_T(); 7 std::cout << "\ntest friend func:\n"; 8 func(); 9 } 10 void test_T() { 11 using std::cout; 12 using std::endl; 13 cout << "T info:" << T::doc << endl; 14 cout << "T objects'max count:" << T::max_cnt << endl; 15 cout << "T objects'current count:" << T::get_cnt() << endl << endl; 16 T t1; 17 cout << "t1="; t1.display(); cout << endl; 18 T t2(3, 4); 19 cout << "t2="; t2.display(); cout << endl; 20 T t3(t2); 21 t3.adjust(2); 22 cout << "t3="; t3.display(); cout << endl; 23 T t4(std::move(t2)); 24 cout << "t4="; t4.display(); cout << endl; 25 cout << "test:T objects'current count:" << T::get_cnt() << endl; 26 }
T.h
1 #pragma once 2 #include<string> 3 class T { 4 public: 5 T(int x = 0, int y = 0); 6 T(const T& t); 7 T(T&& t); 8 ~T(); 9 void adjust(int ratio); 10 void display() const; 11 private: 12 int m1, m2; 13 public: 14 static int get_cnt(); 15 public: 16 static const std::string doc; 17 static const int max_cnt; 18 private: 19 static int cnt; 20 friend void func(); 21 }; 22 void func();
T.cpp
1 #include"T.h" 2 #include<iostream> 3 #include<string> 4 const std::string T::doc{ "a simple class sample" }; 5 const int T::max_cnt = 999; 6 int T::cnt = 0; 7 int T::get_cnt() { 8 return cnt; 9 } 10 T::T(int x, int y) :m1{ x }, m2{ y } { 11 ++cnt; 12 std::cout << "T constructor called.\n"; 13 } 14 T::T(const T& t) :m1{ t.m1 },m2{ t.m2 }{ 15 ++cnt; 16 std::cout << "T copy constructor called.\n"; 17 } 18 T::T(T&& t) :m1{ t.m1 }, m2{ t.m2 } { 19 ++cnt; 20 std::cout << "T move constructor called.\n"; 21 } 22 T::~T() { 23 --cnt; 24 std::cout << "T destructor called.\n"; 25 } 26 void T::adjust(int ratio) { 27 m1 *= ratio; 28 m2 *= ratio; 29 } 30 void T::display() const { 31 std::cout << "(" << m1 << "," << m2 << ")"; 32 } 33 void func() { 34 T t5(42); 35 t5.m2 = 2049; 36 std::cout << "t5="; t5.display(); std::cout << '\n'; 37 std::cout << "func: T objects'current count: " << T::get_cnt() << std::endl; 38 39 }

问题1:不能
问题2:普通构造函数的功能是在创建对象时传入函数接收到的参数,在用传入的参数实例化对象时被调用;复制构造函数的功能是用已存在的同类对象的数据初始化一个新的对象,在形参为const引用类型 ,且实参为现有同类对象的引用时被调用;移动构造函数的功是用临时对象的资源初始化新对象,在形参为右值引用时被调用。
问题3:会报错

重定义的问题
2.
complex.h
1 #pragma once 2 #ifndef COMPLEX_H 3 #define COMPLEX_H 4 #include<string> 5 class Complex { 6 public: 7 static const std::string doc; 8 Complex(); 9 Complex(double r); 10 Complex(double r, double i); 11 Complex(const Complex& other); 12 double get_real() const; 13 double get_imag() const; 14 void add(const Complex& other); 15 friend void output(const Complex& c); 16 friend double abs(const Complex& c); 17 friend Complex add(const Complex& c1, const Complex& c2); 18 friend bool is_equal(const Complex& c1,const Complex& c2); 19 friend bool is_not_equal(const Complex& c1, const Complex& c2); 20 private: 21 double real; 22 double imag; 23 }; 24 #endif
complex.cpp
1 #include"complex.h" 2 #include<iostream> 3 #include<cmath> 4 const std::string Complex::doc = "a simplified complex class"; 5 Complex::Complex() :real(0.0), imag(0.0) {} 6 Complex::Complex(double r) :real(r), imag(0.0) {} 7 Complex::Complex(double r,double i):real(r),imag(i){} 8 Complex::Complex(const Complex&other):real(other.real),imag(other.imag){} 9 double Complex::get_real()const { 10 return real; 11 } 12 double Complex::get_imag()const { 13 return imag; 14 } 15 void Complex::add(const Complex& other) { 16 real += other.real; 17 imag += other.imag; 18 } 19 void output(const Complex& c) { 20 std::cout << c.real; 21 if (c.imag >= 0) { 22 std::cout << "+" << c.imag << "i"; 23 } 24 else { 25 std::cout << "-" << -c.imag << "i"; 26 } 27 } 28 double abs(const Complex& c) { 29 return std::sqrt(c.real * c.real + c.imag * c.imag); 30 } 31 Complex add(const Complex& c1, const Complex& c2) { 32 return Complex(c1.real + c2.real, c1.imag + c2.imag); 33 } 34 bool is_equal(const Complex& c1, const Complex& c2) { 35 return c1.real == c2.real && c1.imag == c2.imag; 36 } 37 38 bool is_not_equal(const Complex& c1, const Complex& c2) { 39 return !is_equal(c1, c2); 40 }
task.cpp
1 #include"complex.h" 2 #include <iostream> 3 #include <iomanip> 4 #include <complex> 5 void test_Complex(); 6 void test_std_complex(); 7 int main() { 8 std::cout << "*******测试1: 自定义类Complex*******\n"; 9 test_Complex(); 10 std::cout << "\n*******测试2: 标准库模板类complex*******\n"; 11 test_std_complex(); 12 } 13 void test_Complex() { 14 using std::cout; 15 using std::endl; 16 using std::boolalpha; 17 cout << "类成员测试: " << endl; 18 cout << Complex::doc << endl << endl; 19 cout << "Complex对象测试: " << endl; 20 Complex c1; 21 Complex c2(3, -4); 22 Complex c3(c2); 23 Complex c4 = c2; 24 const Complex c5(3.5); cout << "c1 = "; output(c1); cout << endl; 25 cout << "c2 = "; output(c2); cout << endl; 26 cout << "c3 = "; output(c3); cout << endl; 27 cout << "c4 = "; output(c4); cout << endl; 28 cout << "c5.real = " << c5.get_real() 29 << ", c5.imag = " << c5.get_imag() << endl << endl; 30 cout << "复数运算测试: " << endl; 31 cout << "abs(c2) = " << abs(c2) << endl; 32 c1.add(c2); 33 cout << "c1 += c2, c1 = "; output(c1); cout << endl; 34 cout << boolalpha; 35 cout << "c1 == c2 : " << is_equal(c1, c2) << endl; 36 cout << "c1 != c2 : " << is_not_equal(c1, c2) << endl; 37 c4 = add(c2, c3); 38 cout << "c4 = c2 + c3, c4 = "; output(c4); cout << endl; 39 } 40 void test_std_complex() { 41 using std::cout; 42 using std::endl; 43 using std::boolalpha; 44 cout << "std::complex<double>对象测试: " << endl; 45 std::complex<double> c1; 46 std::complex<double> c2(3, -4); 47 std::complex<double> c3(c2); 48 std::complex<double> c4 = c2; 49 const std::complex<double> c5(3.5); 50 cout << "c1 = " << c1 << endl; 51 cout << "c2 = " << c2 << endl; 52 cout << "c3 = " << c3 << endl; 53 cout << "c4 = " << c4 << endl; 54 cout << "c5.real = " << c5.real() 55 << ", c5.imag = " << c5.imag() << endl << endl; 56 cout << "复数运算测试: " << endl; 57 cout << "abs(c2) = " << abs(c2) << endl; 58 c1 += c2; 59 cout << "c1 += c2, c1 = " << c1 << endl; 60 cout << boolalpha; 61 cout << "c1 == c2 : " << (c1 == c2) << endl; 62 cout << "c1 != c2 : " << (c1 != c2) << endl; 63 c4 = c2 + c3; 64 cout << "c4 = c2 + c3, c4 = " << c4 << endl; 65 }

问题1:标准库模板类complex和自定义的类Complex相比,标准库模板类的使用形式更为简洁。
函数和运算内在有紧密关联,运算符本质上是特殊的函数,通过对运算符重载,可以对多种模板类执行多种操作。
2.1:否,这些函数完全可以通过公有接口实现,不需要直接访问私有数据
2.2:否,查阅 cppreference,std::abs(std::complex) 是一个非成员函数,不是友元函数。它通过公有接口 real() 和 imag() 来访问复数数据。
2.3:优先使用公有接口,只有在确实需要且能保持良好封装的情况下才使用友元。
问题3:解决方案:将拷贝构造函数声明为 explicit
3,
playercontrol.h
1 #pragma once 2 #include<string> 3 enum class ControlType{Play,Pause,Next,Prev,Stop,Unknown}; 4 class PlayerControl { 5 public: 6 PlayerControl(); 7 ControlType parse(const std::string& control_str); 8 void execute(ControlType cmd)const; 9 static int get_cnt(); 10 private: 11 static int total_cnt; 12 };
playercontrol.cpp
1 #include"playercontrol.h" 2 #include<iostream> 3 #include<algorithm> 4 int PlayerControl::total_cnt = 0; 5 PlayerControl::PlayerControl(){} 6 ControlType PlayerControl::parse(const std::string& control_str) { 7 std::string lower_str; 8 for (auto c : control_str) 9 lower_str += std::tolower(c); 10 ControlType result; 11 if (lower_str == "play") { 12 result = ControlType::Play; 13 } 14 else if (lower_str == "pause") { 15 result = ControlType::Pause; 16 } 17 else if (lower_str == "next") { 18 result = ControlType::Next; 19 } 20 else if (lower_str == "prev") { 21 result = ControlType::Prev; 22 } 23 else if (lower_str == "stop") { 24 result = ControlType::Stop; 25 } 26 else { 27 result = ControlType::Unknown; 28 return result; 29 } 30 total_cnt++; 31 return result; 32 } 33 void PlayerControl::execute(ControlType cmd) const { 34 switch (cmd) { 35 case ControlType::Play: std::cout << "[play] Playing music...\n"; break; 36 case ControlType::Pause: std::cout << "[Pause] Music paused\n"; break; 37 case ControlType::Next: std::cout << "[Next] Skipping to next track\n"; break; 38 case ControlType::Prev: std::cout << "[Prev] Back to previous track\n"; break; 39 case ControlType::Stop: std::cout << "[Stop] Music stopped\n"; break; 40 default: std::cout << "[Error] unknown control\n"; break; 41 } 42 } 43 int PlayerControl::get_cnt() { 44 return total_cnt; 45 }
task.cpp
1 #include "PlayerControl.h" 2 #include <iostream> 3 void test() { 4 PlayerControl controller; 5 std::string control_str; 6 std::cout << "Enter Control: (play/pause/next/prev/stop/quit):\n"; 7 while(std::cin >> control_str) { 8 if(control_str == "quit") 9 break; 10 ControlType cmd = controller.parse(control_str); 11 controller.execute(cmd); 12 std::cout << "Current Player control: " << PlayerControl::get_cnt() << "\n\n"; 13 } 14 } 15 int main() { 16 test(); 17 }

4
Fraction.h
1 #ifndef FRACTION_H 2 #define FRACTION_H 3 4 #include <string> 5 6 class Fraction { 7 public: 8 static const std::string doc; 9 Fraction(int up = 0, int down = 1); 10 Fraction(const Fraction& other); 11 int get_up() const; 12 int get_down() const; 13 Fraction negative() const; 14 15 private: 16 int up; 17 int down; 18 void reduce(); 19 static int gcd(int a, int b); 20 }; 21 22 void output(const Fraction& f); 23 Fraction add(const Fraction& f1, const Fraction& f2); 24 Fraction sub(const Fraction& f1, const Fraction& f2); 25 Fraction mul(const Fraction& f1, const Fraction& f2); 26 Fraction div(const Fraction& f1, const Fraction& f2); 27 28 #endif

问题:自由函数
1.保持良好封装性:不破坏类的信息隐藏原则
2.降低耦合度:函数与类相对独立,易于维护

浙公网安备 33010602011771号