注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

又一个部落格

换过很多备忘录,不知道这本怎么样!

 
 
 

日志

 
 

更进一步的谈谈类  

2010-03-01 18:01:37|  分类: c++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
重载构造函数 Overloading Constructors
#include <iostream>
using namespace std;

class Sample{
public:
    int x;
    int y;
    Sample(){x=y=0;}
    Sample(int i){x=y=i;}
    Sample(int i, int j){x=i;y=j;}
};

int main() {
    Sample t;
    Sample t1(5);
    Sample t2(9,10);

    cout<<"t.x:"<<t.x<<", t.y:"<<t.y<<endl;
    cout<<"t1.x:"<<t1.x<<", t1.y:"<<t1.y<<endl;
    cout<<"t2.x:"<<t2.x<<", t2.y:"<<t2.y<<endl;
    return 0;
}

对象赋值
把一个对象赋值给另外一个对象,是拷贝了一个副本
#include <iostream>
using namespace std;

class Test{
    int a,b;
public:
    void setab(int i, int j){a=i;b=j;}
    void showab(){
        cout << "a is"<<a<<endl;
        cout << "b is" << b<< endl;
    }
};

int main() {
    Test ob1,ob2;

    ob1.setab(10,20);
    ob2.setab(0,0);
    cout << "ob1 before assignment:\n";
    ob1.showab();
    cout << "ob2 before assignment: \n";
    ob2.showab();
    cout <<endl;
    ob2=ob1;

    cout<< "ob1 after assignment:\n";
    ob1.showab();
    cout<< "ob2 after assignment:\n";
    ob2.showab();

    ob1.setab(-1,-1);
    cout<< "ob1 after changing ob1:\n";
    ob1.showab();
    cout<< "ob2 after changing ob1:\n";
    ob2.showab();
    return 0;
}

传递一个对象给函数
作为一个参数传递给函数,和赋值差不多,是一个副本,在函数体内的修改并不会影响到类本身
#include <iostream>
using namespace std;

class MyClass{
    int val;
public:
    MyClass(int i){
        val =i ;
    }
    int getval(){
        return val;
    }
    void setval(int i){
        val = i;
    }
};

void display(MyClass ob){
    cout << ob.getval()<<endl;
}

void change(MyClass ob){
    ob.setval(100);
    cout <<"Value of ob inside change():";
    display(ob);
}

int main() {
    MyClass a(10);
    cout <<"Value of a before calling change():";
    display(a);
    cout <<"Value of a after calling change():";
    display(a);
    return 0;
}

构造函数 析构函数 和对象参数
看下面的例子
#include <iostream>
using namespace std;

class MyClass{
    int val;
public:
    MyClass(int i){
        val =i ;
        cout<<"Inside constructor"<<endl;
    }

    ~MyClass(){
        cout<<"Destructing"<<endl;
    }

    int getval(){return val;}
};

void display(MyClass ob){
    cout << ob.getval()<<endl;
}

int main() {
    MyClass a(10);
    cout <<"Before calling display()."<<endl;
    display(a);
    cout <<"After calling display()."<<endl;
    return 0;
}

输出:
Inside constructor
Before calling display().
10
Destructing
After calling display().
Destructing

注意上面的 构造函数只执行了一次,析构函数执行了两次,为什么会这样呢.
当把一个对象作为参数传递给函数时, 不会调用构造函数, 而是调用 '拷贝构造函数(copy constructor)'.
假如类没有定义 拷贝构造函数, 那么c++会有一个默认的拷贝构造函数

总结:当一个对象的副本创建作为一个函数参数时,正常的构造不调用。相反,默认拷贝构造使一个位的位完全相同的副本。然而,当拷贝被销毁(通常是走出去当函数返回),调用析构函数范围之内。

引用传递对象给函数
#include <iostream>
using namespace std;

class MyClass{
    int val;
public:
    MyClass(int i){
        val =i ;
        cout<<"Inside constructor"<<endl;
    }

    ~MyClass(){
        cout<<"Destructing"<<endl;
    }

    int getval(){return val;}
    void setval(int i){
        val=i;
    }
};

void display(MyClass &ob){
    cout << ob.getval()<<endl;
}

void change(MyClass &ob){
    ob.setval(100);
}

int main() {
    MyClass a(10);
    cout <<"Before calling display()."<<endl;
    display(a);
    cout <<"After calling display()."<<endl;

    change(a);
    cout<<"After calling change()."<<endl;
    display(a);
    return 0;
}

输出:
Inside constructor
Before calling display().
10
After calling display().
After calling change().
100
Destructing

返回对象Returning Objects
#include <iostream>
using namespace std;

class MyClass{
    int val;
public:
    MyClass(int i){
        val =i ;
        cout<<"Inside constructor"<<endl;
    }

    ~MyClass(){
        cout<<"Destructing"<<endl;
    }

    int getval(){return val;}
    MyClass mkBigger(){
        MyClass o(val *2);
        return o;
    }
};

void display(MyClass &ob){
    cout << ob.getval()<<endl;
}


int main() {
    cout <<"Before constructing a."<<endl;
    MyClass a(10);
    cout <<"After constructing a."<<endl<<endl;

    cout<<"Before call to display()."<<endl;
    display(a);
    cout<<"After call to display()."<<endl<<endl;

    cout<<"Before call to mkBigger()."<<endl;
    a = a.mkBigger();
    cout<<"After call to mkBigger()."<<endl<<endl;

    cout<<"Before call to display()."<<endl;
    display(a);
    cout<<"After call to display()."<<endl;

    return 0;
}

输出
Before constructing a.
Inside constructor
After constructing a.

Before call to display().
10
After call to display().

Before call to mkBigger().
Inside constructor
Destructing
Destructing                ----注意 这里有两个 Destructing ,其实和编译器有关系,用vs2008 有两个, 用eclipse只有1个
After call to mkBigger().

Before call to display().
20
After call to display().
Destructing

可以看到,当调用 mkBigger后,有一次构造和析构,说明,返回对象时候,是进行对象的拷贝,拷贝的时候,会用一个临时的对象保存这个拷贝,函数结束后,临时对象被销毁.

当一个对象的值给另外一个对象有两种情况
1. 转让
2. 初始化
    初始化出现在这3种情况
    1.申明一个对象的时候
    2.作为参数传递个函数,非引用
    3.当产生一个零时的对象的时候,通常是函数返回对象的时候

下面情况将出现使用拷贝函数
MyClass x=y;
func1(y);
y=func2();
下面情况不出现拷贝函数
x=y;

拷贝构造函数只出现在初始化对象的时候,不出现在转让对象的时候
拷贝函数的写法
classname (const classname &obj) { // body of constructor }

#include <iostream>
using namespace std;

class MyClass{
    int val;
    int copynumber;
public:
    MyClass(int i){
        val =i ;
        copynumber=0;
        cout<<"Inside normal constructor"<<endl;
    }
    //和构造函数一样,函数名称是类名,只是参数不一样,其实可以理解为重载
    MyClass(const MyClass &o){
        val = o.val;
        copynumber = o.copynumber + 1;
        cout <<"Inside copy constructor."<<endl;
    }

    ~MyClass(){
        if(copynumber ==0)
            cout<<"Destructing original."<<endl;
        else
            cout<<"Destructing copy "<<copynumber<<endl;
        cout<<"Destructing"<<endl;
    }

    int getval(){return val;}

};

void display(MyClass ob){
    cout << ob.getval()<<endl;
}


int main() {
    MyClass a(10);
    display(a);

    return 0;
}

输出
Inside normal constructor
Inside copy constructor.
10
Destructing copy 1
Destructing
Destructing original.
Destructing

朋友函数
普通的一个非类内部函数是不能访问类的私有成员的,如果申明为朋友函数就可以访问私有成员
#include <iostream>
using namespace std;

class MyClass{
    int a,b;
public:
    MyClass(int i, int j){
        a=i;
        b=j;
    }
    friend int comDenom(MyClass x);
};

int comDenom(MyClass x){
    int max = x.a<x.b?x.a:x.b;
    for(int i=2;i<=max;i++)
        if((x.a%i)==0 && (x.b%i)==0)return i;
    return 0;
}

int main() {
    MyClass n(18,111);
    if(comDenom(n))
        cout<<"Common denominator is "<<comDenom(n)<<endl;
    else
        cout<<"No common denominator."<<endl;

    return 0;
}

朋友函数也可以同时出现在两个类中,看下面的例子
#include <iostream>
using namespace std;
//需要预先申明一下,不然下面的朋友函数定义的时候就会报错
class Cylinder;

enum colors{red,green,yellow};

class Cube{
    colors color;
public :
    Cube (colors c){color=c;}
    friend bool sameColor(Cube x, Cylinder y);
    ~Cube(){
        cout<<"xxx";
    }
};

class Cylinder{
    colors color;
public:
    Cylinder(colors c){color=c;}
    friend bool sameColor(Cube x, Cylinder y);
};

bool sameColor(Cube x,Cylinder y)
{
    if(x.color==y.color)
        return true;
    else
        return false;
}
int main() {
    Cube cubel(red);
    Cube cube2(green);
    Cylinder cy1(green);

    if(sameColor(cubel,cy1))
        cout<<"cube1 and cy1 are the same color"<<endl;
    else
        cout<<"cube1 and cy1 are different colors"<<endl;

    if(sameColor(cube2,cy1))
        cout<<"cube2 and cy1 are the same color"<<endl;
    else
        cout<<"cube2 and cy1 are different colors"<<endl;

    return 0;
}

朋友函数也可以是某个类的成员函数
#include <iostream>
using namespace std;
//需要预先申明一下,不然下面的朋友函数定义的时候就会报错
class Cylinder;

enum colors{red,green,yellow};

class Cube{
    colors color;
public :
    Cube (colors c){color=c;}
    bool sameColor(Cylinder &y);
};

class Cylinder{
    colors color;
public:
    Cylinder(colors c){color=c;}
    friend bool Cube::sameColor(Cylinder &y);
};

bool Cube::sameColor(Cylinder &y)
{
    if(color==y.color)
        return true;
    else
        return false;
}
int main() {
    Cube cubel(red);
    Cube cube2(green);
    Cylinder cy1(green);

    if(cubel.sameColor(cy1))
        cout<<"cube1 and cy1 are the same color"<<endl;
    else
        cout<<"cube1 and cy1 are different colors"<<endl;

    if(cube2.sameColor(cy1))
        cout<<"cube2 and cy1 are the same color"<<endl;
    else
        cout<<"cube2 and cy1 are different colors"<<endl;

    return 0;
}


结构和联盟Structures and Unions
结构的成员默认都是 public的,结构其实就是另外一种方式来申明类
#include <iostream>
using namespace std;

struct Test{
    int get_i(){return i;}
    void put_i(int j){i=j;}
private:
    int i;
};


int main() {
    Test s;
    s.put_i(10);
    cout<<s.get_i();
    return 0;
}

联盟Unions
union utype{
    short int i;
    char ch;
};

下面一个例子
#include <iostream>
using namespace std;

union u_type{
    u_type(short int a){i=a;}
    u_type(char x,char y){ch[0]=x;ch[1]=y;}
    void showchars(){
        cout <<ch[0]<<" ";
        cout <<ch[1]<<endl;
    }
    short int i;
    char ch[2];
};


int main() {
    u_type u(99);
    u_type u2('x','y');

    cout <<"u as integer: ";
    cout <<u.i<<endl;
    cout <<"u as chars:";
    u.showchars();

    cout <<"u2 as integer: ";
    cout <<u2.i<<endl;
    cout <<"u2 as chars:";
    u2.showchars();
    return 0;
}

匿名联盟 Anonymous Unions
要注意联盟的变量名字,看下面的例子
联盟中的变量范围和本地变量是一养的,所以要注意变量名字问题
#include <iostream>
using namespace std;

int main() {
    union{ long l;
        double d;
        char s[4];
    };
    l = 100000;
    cout <<l<<" "<< d << endl;

    d = 123.2345;
    cout<<d<<" "<<l<<endl;

    strcpy(s,"hi");
    cout<<s;

    return 0;
}


this关键字
每当类的一个成员函数执行的时候,一个默认的指针this被传递,这个指针指向正在执行的这个类对象本身.


运算符重载
type classname::operator#(arg-list) { // operations }

#include <iostream>
using namespace std;

class ThreeD{
    int x, y, z;
public:
    ThreeD(){x=y=z=0;}
    ThreeD(int i, int j, int k){x=i;y=j;z=k;}

    ThreeD operator+(ThreeD op2);
    ThreeD operator=(ThreeD op2);

    void show();
};

ThreeD ThreeD::operator +(ThreeD op2){
    ThreeD temp;

    temp.x=x+op2.x;
    temp.y=y+op2.y;
    temp.z=z+op2.z;
    //请注意,这里返回的是一个新的类
    return temp;
}

ThreeD ThreeD::operator =(ThreeD op2){
    x=op2.x;
    y=op2.y;
    z=op2.z;
    //this指向的  操作符左边的变量,是隐式的传递给函数的, op2指向的是操作符右边的变量
    //而这里返回的是一个原先的被修改的类
    return *this;
}

void ThreeD::show(){
    cout<<x<<", ";
    cout<<y<<", ";
    cout<<z<<endl;
}

int main() {
    ThreeD a(1,2,3),b(10,10,10),c;

    cout << "Original value of a:";
    a.show();

    cout << "Original value of b:";
    b.show();

    c =a +b;
    cout << "Value of c after c = a+b: ";
    c.show();
    cout << endl;

    c = a+b+c;
    cout << "Value of c after c = a+b+c: ";
    c.show();
    cout << endl;

    c = b =a;
    cout << "Value of c after c = b =a: ";
    c.show();
    cout << "Value of c after c = b =a: ";
    b.show();

    return 0;
}

使用成员函数 重载1元操作符

#include <iostream>
using namespace std;

class ThreeD{
    int x, y, z;
public:
    ThreeD(){x=y=z=0;}
    ThreeD(int i, int j, int k){x=i;y=j;z=k;}

    ThreeD operator ++();

    void show();
};

ThreeD ThreeD::operator ++(){
    x++;
    y++;
    z++;
    return *this;
}
void ThreeD::show(){
    cout<<x<<", ";
    cout<<y<<", ";
    cout<<z<<endl;
}

int main() {
    ThreeD a(1,2,3);

    cout << "Original value of a:";
    a.show();
    //注意这里是 ++在前面
    ++a;
    cout << "Value after ++a: ";
    a.show();
    cout << endl;

    return 0;
}

如果要后 ++呢
#include <iostream>
using namespace std;

class ThreeD{
    int x, y, z;
public:
    ThreeD(){x=y=z=0;}
    ThreeD(int i, int j, int k){x=i;y=j;z=k;}

    ThreeD operator ++(int notused);

    void show();
};

//注意这个参数,没有被使用过,也不是 Threed类型
ThreeD ThreeD::operator ++(int notused){
    //这里为什么要返回原先的值呢,因为 后++ 操作符的意思就是这样,执行完++后,值才被改变
    ThreeD temp = *this;
    x++;
    y++;
    z++;
    return temp;
}
void ThreeD::show(){

    cout<<x<<", ";
    cout<<y<<", ";
    cout<<z<<endl;
}

int main() {
    ThreeD a(1,2,3);

    cout << "Original value of a:";
    a.show();
    //注意这里是 ++在后面
    a++;
    cout << "Value after ++a: ";
    a.show();
    cout << endl;

    return 0;
}


用非成员函数的方法重载操作符
#include <iostream>
using namespace std;

class ThreeD{
    int x, y, z;
public:
    ThreeD(){x=y=z=0;}
    ThreeD(int i, int j, int k){x=i;y=j;z=k;}
    //因为要访问私有函数,所以必须要用 朋友函数才可以
    friend ThreeD operator+(ThreeD op1, ThreeD op2);

    void show();
};

ThreeD operator +(ThreeD op1, ThreeD op2){
    ThreeD temp;

    temp.x=op1.x+op2.x;
    temp.y=op1.y+op2.y;
    temp.z=op1.z+op2.z;
    return temp;
}

void ThreeD::show(){
    cout<<x<<", ";
    cout<<y<<", ";
    cout<<z<<endl;
}

int main() {
    ThreeD a(1,2,3),b(10,10,10),c;

    cout << "Original value of a:";
    a.show();

    cout << "Original value of b:";
    b.show();

    c =a +b;
    cout << "Value of c after c = a+b: ";
    c.show();
    cout << endl;

    c = a+b+c;
    cout << "Value of c after c = a+b+c: ";
    c.show();
    cout << endl;


    return 0;
}

假如操作符两边的对象不相同,那么往往需要重载两次操作符,看下面的例子
#include <iostream>
using namespace std;

class ThreeD{
    int x, y, z;
public:
    ThreeD(){x=y=z=0;}
    ThreeD(int i, int j, int k){x=i;y=j;z=k;}
    //因为需要符合  1 + a 和 a + 1的情况,所以需要重载两次
    friend ThreeD operator+(ThreeD op1, int i);
    friend ThreeD operator+(int i, ThreeD op1 );

    void show();
};

ThreeD operator +(ThreeD op1, int i){
    ThreeD temp;

    temp.x=op1.x+i;
    temp.y=op1.y+i;
    temp.z=op1.z+i;
    return temp;
}
ThreeD operator +(int i, ThreeD op1){
    ThreeD temp;

    temp.x=op1.x+i;
    temp.y=op1.y+i;
    temp.z=op1.z+i;
    return temp;
}

void ThreeD::show(){
    cout<<x<<", ";
    cout<<y<<", ";
    cout<<z<<endl;
}

int main() {
    ThreeD a(1,2,3), c;

    cout << "Original value of a:";
    a.show();

    c =a + 1;
    cout << "Value of c after c =a + 1: ";
    c.show();
    cout << endl;

    c = 2+ a + 3;
    cout << "Value of c after c = 2+ a + 3: ";
    c.show();
    cout << endl;

    return 0;
}

  评论这张
 
阅读(105)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017