构造


#include<iostream>
using namespace std;
class Vector
{
    int x,y;
public:
    Vector(){};//默认构造函数
    Vector(int x1,int y1)//重载构造函数
    {
        x=x1;y=y1;
    }
    Vector operator+(Vector v)//成员函数方式重载运算符"+"
    {
        Vector tmp;//定义一个tmp对象
        tmp.x=x+v.x;
        tmp.y=y+v.y;
        return tmp;//返回tmp对象
    }
    Vector operator-(Vector v)//成员函数方式重载运算符"-"
    {
        Vector tmp;//定义一个tmp对象
        tmp.x=x-v.x;
        tmp.y=y-v.y;
        return tmp;//返回tmp对象
    }
    void display()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
};
void main()
{
    Vector v1(6,8),v2(3,6),v3,v4;
    cout<<"v1=";
    v1.display();
    cout<<"v2=";
    v2.display();
    v3=v1+v2;
    cout<<"v1+v2=";
    v3.display();
    v4=v1-v2;
    cout<<"v1-v2=";
    v4.display();
    system("pause");
}
//-------------
#include<iostream>
using namespace std;
class Vector1
{
    int x,y;
public:
    Vector1(){};
    Vector1(int x1,int y1){x=x1;y=y1;}
    friend Vector1 operator+(Vector1 v1,Vector1 v2)//友元函数方式
    {
        Vector1 tmp;
        tmp.x=v1.x+v2.x;
        tmp.y=v1.y+v2.y;
        return tmp;
    }
    friend Vector1 operator-(Vector1 v1,Vector1 v2)//友元函数方式
    {
        Vector1 tmp;
        tmp.x=v1.x-v2.x;
        tmp.y=v1.y-v2.y;
        return tmp;
    }
    void display()
    {
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
};
void main()
{
    Vector1 v1(6,8),v2(3,6),v3,v4;
    cout<<"v1=";
    v1.display();
    cout<<"v2=";
    v2.display();
    v3=v1+v2;
    cout<<"v1+v2=";
    v3.display();
    v4=v1-v2;
    cout<<"v1-v2=";
    v4.display();
    system("pause");
}
//------------------
/*bool operator<(const Date1 d1)
    bool operator>(const Date1 d1)
    bool operator==(const Date1 d1)*/
#include<iostream>
using namespace std;
class  Date1
{
    int year;int month;int day;
public:
    Date1(){};//默认构造函数,第一个没用,系统预留
    Date1(int y,int m,int d)//重载构造函数
    {
        year=y;month=m;day=d;
    }
    Date1(const Date1 &d1)//复制构造函数,第三个函数好像是复制第二个函数里面的
    {
        year=d1.year;
        month=d1.month;
        day=d1.day;
    }
    bool operator<(const Date1 d1)
    {
        if((year<d1.year)||(year=d1.year&&month<d1.month)||(year==d1.year&&month==d1.month&&day<d1.day))
            return true;
        else
            return false;
    }
    bool operator==(const Date1 d1)
    {
        if(year==d1.year&&month==d1.month&&day&&d1.day)
            return true;
        else
            return false;
    }
    bool operator>(const Date1 d1)
    {
        if((year>d1.year)||(year=d1.year&&month>d1.month)||(year==d1.year&&month==d1.month&&day>d1.day))
            return true;
        else
            return false;
    }
    void disp()
    {
        cout<<year<<"."<<month<<"."<<day<<endl;
    }
};
void main()
{
    Date1 d1(2008,10,1),d2(2010,10,1),d3(d1);
    cout<<"d1:";
    d1.disp();
    cout<<"d2:";
    d2.disp();
    cout<<"d3:";
    d3.disp();
    cout<<"d1<d2:"<<(d1<d2)<<endl;
    cout<<"d1>d2:"<<(d1>d2)<<endl;
    cout<<"d1==d2:"<<(d1==d2)<<endl;
    cout<<"d1==d3:"<<(d1==d3)<<endl;
    system("pause");
}
//-----------------

 

  1operator+ 一般可以间接的通过operator+=来实现 2008-05-05 17:51:43
  2 分类: C/C++
  3 小技巧:operator+ 一般可以间接的通过operator+=来实现
  4 
  5 class Matrix {
  6 public:
  7     Matrix& operator+=(const Matrix& rhs) {
  8         // ...
  9         return *this;
 10     }
 11 
 12     const Matrix operator+ (const Matrix& rhs) const {
 13         Matrix tmp(*this);      // 调用拷贝构造函数,通过复制产生一个新的object
 14         tmp += rhs;             // 利用operator += 实现operator +
 15         return tmp;             // 返回计算结果
 16     };
 17 };
 18 
 19 
 20 
 21 
 22 看下面的代码:
 23 int func(int j) {
 24     int i = 30;
 25     i += j;
 26     return i;
 27 }
 28 这个函数很简单,大家也都认为它没有语法错误。函数返回时,变量i会被销毁,但是函数仍然成功的将i的值返回出来了。呵呵,有点神奇。类比一下:
 29     const Matrix operator+ (const Matrix& rhs) const {
 30         Matrix tmp(*this);      // 调用拷贝构造函数,通过复制产生一个新的object
 31         tmp += rhs;             // 利用operator += 实现operator +
 32         return tmp;             // 返回计算结果
 33     };
 34 函数返回时,变量tmp会被销毁,但是函数仍然可以成功的将tmp的值返回出来。
 35 
 36 注意这句return tmp;其中所隐藏的程序行为。函数返回一个值时,先把要返回的值复制一份(调用copy constructor,拷贝构造函数),放到别处,然后再销毁函数中各种需要销毁的变量,再将控制权交还给函数的调用者,调用者看到的返回值实际上是复制的值。
 37 
 38 举例来说。比如我写
 39 Matrix m = m1 + m2;
 40 则m1+m2会调用Matrix::operator +(函数),函数返回时,先将返回值复制一份(调用copy constructor,拷贝构造函数),然后销毁函数中的变量tmp。函数返回后,利用复制好的值对变量m进行构造。当Matrix m = m1 + m2;这一整条语句都执行完毕后,m1+m2得到的值因为是临时值,不再使用,所以进行销毁,也就是说在这个时候把复制的值销毁。
 41 这样看来,短短的一句Matrix m = m1 + m2;就要产生多个对象并进行销毁。(第一个:operator +中的tmp对象,第二个:返回时需要复制产生一个临时对象,第三个:正式需要的对象m)构造函数和析构函数被大量的调用,效率较低。这种情况下,编译器一般会对其进行优化,尽可能产生较少的对象,减少构造函数和析构函数的调用。但是最终要产生多少对象,这完全取决于编译器的优化能力:有的编译器可能完全不优化,产生三个对象;有的编译器则只产生两个对象(返回时复制一份的对象本身就是上一层函数的变量m);最理想的情况就是只产生一个对象(变量tmp,返回时复制一份的对象,上一层函数的变量m三者合一)。
 42 可以做这样一个实验,定义一个类,在构造函数、拷贝构造函数、析构函数中分别输出不同的信息(例如cout << "construct" << endl;),然后定义一个函数来返回这个类的对象。可以看到不同的编译器可能输出不同的结果。
 43 #include <iostream>
 44 using namespace std;
 45 class Test {
 46 public:
 47     Test()            { cout << "construct" << endl; }
 48     Test(const Test&) { cout << "copy construct" << endl; }
 49     ~Test()           { cout << "descruct" << endl; }
 50 };
 51 Test func() {
 52     Test t;
 53     return t;
 54 }
 55 int main() {
 56     Test t = func();
 57     return 0;
 58 }
 59 
 60 我用vc2005测试,debug模式构造了两个对象(输出四行),release模式则只构造了一个对象(输出两行)。
 61 
 62 注意以下几种用法是错误或者不推荐的。
 63 1. 返回即将被销毁的变量的引用。错误的做法。因为变量被销毁,引用它也就没有意义。
 64 2. 返回指向即将被销毁的变量的指针。错误的做法。理由同上。
 65 3. 通过new分配内存并创建对象,返回它的引用或返回指向它的指针。不推荐。例如:
 66 Matrix m = (m1 + m2) + m3;
 67 则m1+m2的结果一直保存着,无法进行释放。
 68 必须写:
 69 Matrix* pTemp1 = &(m1 + m2);
 70 Matrix* pTemp2 = &(*pTemp1 + m3);
 71 m = *pTemp2;
 72 delete pTemp1;
 73 delete pTemp2;
 74 这种烦琐的方式显然不是我们想要的。
 75 4. 定义一个static变量,返回它的引用或返回指向它的指针。不推荐。
 76 Matrix m = m1 + m2;           // 没问题
 77 Matrix m = (m1+m2) + (m3+m4); // 错误
 78 因为用了static,每次相加的结果都是放到同一个变量中进行保存的。C++没有规定到底先计算m1+m2还是先计算m3+m4。如果先计算m1+m2,则后来计算m3+m4时就会把m1+m2的结果覆盖;如果先计算m3+m4,则后来计算m1+m2时就会把m3+m3的结果覆盖,无论怎么计算,最后都无法得到正确的结果。
 79 
 80 引用:
 81 不过,拷贝构造函数,operator =操作符,还有析构函数一般都要一起出现。
 82 假如其中一个可以不要,那么一般三个都可以不要。
 83 
 84 如果不定义自己的拷贝构造函数、operator =、析构函数,则C++编译器会自动产生一个默认的。实际使用时,先考虑使用默认的拷贝构造函数、operator=、析构函数是否满足需要,如果不满足,就自己定义之。通常,如果成员中使用了指针,就需要自己定义。
 85 
 86 最后,operator +返回的类型要加上const。这是为了避免出现下面的情况:
 87 (m1 + m2) = m3;
 88 如果m1+m2是一个Matrix类型,则它可以被赋值(调用operator=),但是上面的语句是不合逻辑的,不应该被允许。只要让m1+m2是一个const Matrix类型,就可以让上面的语句编译出错。从而避免这种不合逻辑的写法。
 89 
 90 
 91 
 92 小结:
 93 编写加法运算符,最合理的实现可能就是这个了:
 94     const Matrix operator+ (const Matrix& rhs) const {
 95         Matrix tmp(*this);      // 调用拷贝构造函数,通过复制产生一个新的object
 96         tmp += rhs;             // 利用operator += 实现operator +
 97         return tmp;             // 返回计算结果
 98     };
 99 程序必须先追求正确,然后才能追求高效。从上面四种不推荐的情况来看,返回引用或者指针都不是好的做法(有些做法是错误的,有些做法隐含了潜在错误),因此只好返回实际的对象了。
100 通过编译器的优化,返回一个对象的效率并没有大家想象的那么不堪,实际构造对象的个数往往并不多。没有必要为了这点性能去担忧。
101 
102 
103 
104 
105 #include<iostream>
106 using namespace std;
107 class MyClass2
108 {
109     int n;
110 public:
111     MyClass2(int i){n=i;}
112     operator ++(){n++;}//vc6.0支持,vs2012不支持
113     operator++(int){n+=2;}
114     void display()
115     {
116         cout<<"n="<<n<<endl;
117     }
118 };
119 void main()
120 {
121     MyClass2 A(5),B(5);
122     A++;
123     ++B;
124     A.display();
125     B.display();
126     system("pause");
127 }
128 #include<iostream>
129 using namespace std;
130 class MyClass2
131 {
132     int n;
133 public:
134     MyClass2(int i){n=i;}
135     const int operator ++(){n++;return n;}
136     const int operator++(int){n+=2;return n;}
137     void display()
138     {
139         cout<<"n="<<n<<endl;
140     }
141 };
142 void main()
143 {
144     MyClass2 A(5),B(5);
145     A++;
146     ++B;
147     A.display();
148     B.display();
149     system("pause");
150 }

 

posted @ 2013-05-27 14:24  herizai  阅读(247)  评论(0编辑  收藏  举报