《C++程序设计POJ》《WEEK3 类和对象进阶》《复制构造函数》《类型转换构造函数》
类型转换构造函数 目的
•实现类型的自动转换 特点
•只有一个参数
•不是复制构造函数 编译系统会自动调用 转换构造函数
建立一个 临时对象 / 临时变量
class A { public: int a; A(int a) :a(a) {} A reta() { return a; } }; int main() { A a(2); A b = a.reta(); // 将类型是 int 的变量 赋值给 类型为 A 的对象,调用了 类型转换构造函数 A c = 3; cout<<b.a<<"\n"<<c.a<<endl; return 0; } // 结果是输出2和3
class Complex { public: double real, imag; Complex( int i ) { //类型转换构造函数 cout << “IntConstructor called” << endl; real = i; imag = 0; } Complex( double r, double i ) { real = r; imag = i; } }; int main () { Complex c1(7, 8); Complex c2 = 12; c1 = 9; // 9被自动转换成一个临时Complex对象 cout << c1.real << "," << c1.imag << endl; return 0; } 输出: IntConstructor called IntConstructor called 9,0
复制构造函数
Complex(const Complex & c)
X::X(X&)
X::X(const X &)
二者选一,后者能以常量对象作为参数
复制构造函数起作用的三种情况:
1)当用一个对象去初始化同类的另一个对象时。
Complex c2(c1);
Complex c2 = c1; //初始化语句,非赋值语句
Complex c2(c1);
2)如果某函数有一个参数是类 A 的对象, 那么该函数被调用时,类A的复制构造函数将被调用。
class A
{
public:
A() { };
A( A & a)
{
cout << "Copy constructor called" <<endl;
}
};
#include<iostream> #include<cstdio> using namespace std; #if 0 /*当用一个对象去初始化同类的另一个对象时。*/ class Complex { public: double real, imag; Complex() {} Complex(const Complex &c) { real = c.real; imag = c.imag; cout << "copy constructor called"; } }; int main() { Complex c1; Complex c2(c1); while (1); } #endif /*如果某函数有一个参数是类 A 的对象, 那么该函数被调用时,类A的复制构造函数将被调用*/ #if 0 class A { public: A() {}; A(A&a) { cout << "Copy constructor called" << endl; } }; void Func(A a1) {} int main() { A a2; Func(a2); while (1); return 0; } #endif /*如果函数的返回值是类A的对象时,则函数返回时, A的复制构造函数被调*/ class A { public: int v; A(int n) { v = n; } A(const A & a) { v = a.v; cout << "Copy constructor called" << endl; } }; A Func() { A b(4); return b; } int main() { cout << Func().v << endl; while (1); return 0; }
//类型转换构造函数 #include<iostream> using namespace std; class Complex { public: double real, imag; Complex(int i) { // 类型转换构造函数 cout << "intConstructor called" << endl; real = i; imag = 0; } Complex(double r, double i) { real = r; imag = i; } }; int main() { Complex c1(7, 8); Complex c2 = 12; c1 = 9; cout << c1.real << "," << c1.imag << endl; while (1); return 0; }
析构函数 ~
没有参数和返回值
对象消亡时,自动被调用
如果没写析构函数,则编译器生成缺省的析构函数
析构函数是自动调用的!!!
//类型转换构造函数 #include<iostream> #include<stdlib.h> using namespace std; #if 0 class Complex { public: double real, imag; Complex(int i) { // 类型转换构造函数 cout << "intConstructor called" << endl; real = i; imag = 0; } Complex(double r, double i) { real = r; imag = i; } }; int main() { Complex c1(7, 8); Complex c2 = 12; c1 = 9; cout << c1.real << "," << c1.imag << endl; while (1); return 0; } #endif #if 0 class Ctest { public: ~Ctest() { cout << "destructor called" << endl; } }; int main() { Ctest array[2]; cout << "End Main" << endl; //while (1); system("PAUSE"); return 0; } #endif class Demo { int id; public: Demo(int i) { id = i; cout << "id=" << id << "constructed" << endl; } ~Demo() { cout << "id=" << id << "destructed" << endl; } }; Demo d1(1); // 全局变量最后消亡 void Func() { static Demo d2(2); // 静态变量在程序结束后消亡 Demo d3(3); cout << "Func" << endl; } int main() { Demo d4(4); d4 = 6; // 类型转换构造函数,6被自动转换成一个临时Demo对象 cout << "main" << endl; { Demo d5(5); }//作用域结束,对象消亡 Func(); cout << "main ends" << endl; //while (1); system("PAUSE"); return 0; }
静态成员变量和静态成员函数 STATIC
sizeof运算符不会计算静态成员变量
普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享
静态成员变量本质是全局变量
静态成员函数本质上是全局函数
必须在定义类的文件中对静态成员变量进行一次说明
普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用与某个对象
设置静态成员这种机制的目的是将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。
静态成员函数不作用在对象上!!!
复制构造函数 初始化对象 有坑!!!
解决方案:写一个复制构造函数
#include<iostream> using namespace std; class CRectangle { private: int w, h; static int nTotalArea; static int nTotalNumber; public: CRectangle(int w_, int h_); ~CRectangle(); static void PrintTotal(); CRectangle::CRectangle(CRectangle &r) { w = r.w; h = r.h; nTotalNumber++; nTotalArea += w*h; } }; CRectangle::CRectangle(int w_, int h_) { w = w_; h = h_; nTotalNumber++; nTotalArea += w*h; } CRectangle::~CRectangle() { nTotalNumber--; nTotalArea -= w*h; } void CRectangle::PrintTotal() { cout << nTotalNumber << "," << nTotalArea << endl; } int CRectangle::nTotalNumber = 0; int CRectangle::nTotalArea = 0; // 必须在定义类的文件中对静态成员变量进行一次说明 //或初始化。否则编译能通过,链接不能通过。 int main() { CRectangle r1(3, 3), r2(2, 2); //cout << CRectangle::nTotalNumber; CRectangle::PrintTotal(); r1.PrintTotal(); while (1); return 0; } //在静态成员函数中,不能访问非静态成员变量, 也不能调用非静态成员函数。 //void CRectangle::PrintTotal() //{ // cout << w << "," << nTotalNumber << "," << nTotalArea << endl; //} //CRectangle::PrintTotal();//解释不通,w 到底是属于那个对象的?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix