代码改变世界

参数传递 强制类型转换 自动类型转换 临时变量

2012-10-26 16:37  Ball Cactus  阅读(965)  评论(0编辑  收藏  举报

0  关于参数传递

类A, 有一个int的数据成员
0.1  test1(int i),若A中有一个operator int()的强制类型转换,可以直接传对象。
  A a;
  test1(a);
0.2  test2(A b),若A中有一个A(int i)的构造函数,可以直接将int作为参数
  int i = 10;
  test2(i);//这里自动调用A的构造函数,若传的是A的对象,则调用A的拷贝构造函数。如果传入的实参和形参类型不一致时,如果编译器能找到以上两种转换,则自动转换,否则会报类型不一致错误。

1  自动类型转换
自动转换发生在不同数据类型的变量混合运算时,由编译系统自动完成。

2  强制类型转换
2.1  const char *可以被强制转换成char *从而改变字符串的内容
2.2  重载强制类型转换运算符

class Complex
{
private:
    int a;
    int b;
public:
    Complex(int i=0, int j=0)
    {
        a=i;
        b=j;
    }
    void print()
    {
        cout<<"the value is: "<<a<<"+"<<b<<"j\n";
    }
    Complex operator +(const Complex &m)
    {
        Complex tmp;
        tmp.a = a+m.a;
        tmp.b = b+m.b;
        return tmp;
    }
    operator int ()    //重载强制转换类型转换
    {
        cout<<"重载强制类型转换运算符\n";
        return a;
    }
};
int main()
{
    Complex com1(2,2),com2(3,3);
    Complex com3;
    com3 = com1+com2;
    com3.print();    //5+5j
    int t = (int)com3;
    cout<<t<<endl; //5
    int s = 8;
    cout<<s+com1<<endl;//10,系统自动将com1强制类型转换为int
    return 0;
}

3 临时变量
3.1  构造函数的显式调用和隐式调用...不知道术语是什么
以下来自:www.wutianqi.com/?p=2730
你可以试试以下代码, 会发现问题。
class A{
public:
A(){};
A(int t)
{
cout<<"Constucting…."<<endl;
a=t;
cout<<"a="<<a<<endl;
}
private:
int a;
};
int main()
{
cout<<"a=12:"<<endl;
A a;
a=12;
cout<<"A b(13)"<<endl;
A b(13);
cin.get ();
}
a=13,的整个过程其实是,A(int t)先使用13建立一个对象,然后将这个对象赋值给a,这就是所谓隐式转换。
当你使用explicit修饰的时候,也就把隐式转换关闭了,也就是说你告诉编译器,只有我显示指出调用该构造函数才调用。所以,在有explicit的时候a=13就不能通过了,因为编译器不会自动调用构造函数来帮你完成隐式转换。
类似:
CString str("abc");
char *pstr = "bean";
str = pstr;//这个过程是先隐式调用CString的构造函数创建一个CString对象,再通过赋值函数将其赋值给str
PS:拷贝构造函数的三种用法:初始化、传参、函数返回值。

class E
{
public:
    E()
    {
        cout<<"E()"<<endl;
        a = 1;
    }
    E(int i)
    {
        cout<<"E(int i)"<<endl;
        a = i;
    }
    E(const E &e)
    {
        cout<<"拷贝函数"<<endl;
        a = e.a;
    }
    operator = (const E &e)
    {
        cout<<"赋值函数"<<endl;
        a = e.a;
    }
private:
    int a;
};
E fun(E e)
{
    cout<<"fun(E e)"<<endl;
    return e;
}
int main()
{
/*    E x;
    int j = 10;
    x = j;//输出为:E()---E(int i)---赋值函数
*/
    E e1, e2;
    fun(2);//输出为:E(int i)---fun(E e)---拷贝函数
    cout<<endl;
    fun(e1);//输出为:拷贝函数---fun(E e)---拷贝函数
    cout<<endl;
    e2 = fun(3);//输出为:E(int i)---fun(E e)---拷贝函数---赋值函数
    cout<<endl;
    e2 = fun(e1);//输出为:拷贝函数---fun(E e)---拷贝函数---赋值函数
    cout<<endl;
}

3.2
CString类向const char *转换
char a[100];
CString str("aaaaaa");
strncpy(a,(LPCTSTR)str,sizeof(a));或strncpy(a,str,sizeof(a));   
以上两种用法都是正确地. 因为strncpy的第二个参数类型为const char *.所以编译器会自动将CString类转换成const char *
PS:
为什么char *p2 = (LPCSTR)str;可以,而char *p2 = (LPSTR)str;不可以
ansi情况下,LPCTSTR 就是 const char*(LPCSTR)
3.3  临时变量在哪些情况下用到?(传值 返回值...)
CString CTestDlgDlg::TestString(LPCTSTR str1, CString str2, char * str3)
{
    MessageBox(str1);
    MessageBox(str2);
    return "abc";
}
3.4 派生类指针向基类指针转换由编译器自动完成,反之,需要强制类型转换,包括传参和赋值
CtestcefDlg *dDlg = AfxGetMainWnd();//错误,不能从CWnd *转换成CDlg *

class Base
{
public:
    Base(){b = 10;}
    int b;
    void printb(){cout<<"b:"<<b<<endl;}
};
class Derive:public Base
{
public:
    Derive(){d = 20;}
    int d;
    void printd(){printb();cout<<"d:"<<d<<endl;}
};

int main()
{
    Base *pb1, *pb2;
    Derive *pd1, *pd2;
    pb1 = new Base();
    pd1 = new Derive();

    pb2 = pd1;//派生类指针向基类指针转换由编译器自动完成
    pd2 = (Derive *)pb1;//反之,需要强制类型转换
/*
    pd2->printb();//OK
    pd2->printd();//ERROR: 输出的d没有赋值
*/
/*
    pb2->printb();//OK
    pb2->printd();//ERROR: 'printd' : is not a member of 'Base'
    ((Derive *)pb2)->printd();//OK
*/
}