值,引用,指针:
http://zhidao.baidu.com/question/52947711.html
#include <iostream.h> #include <iomanip.h> void fun1(int a,int b); void fun2(int& a,int& b); void fun3(int* a,int* b);
void main() { int x=5,y=10; cout<<x<<setw(10)<<y<<endl; fun1(x,y); cout<<x<<setw(10)<<y<<endl; fun2(x,y); cout<<x<<setw(10)<<y<<endl; fun3(&x,&y); cout<<x<<setw(10)<<y<<endl; }
void fun1(int a,int b) { a=a+b; b=b*2; cout<<"fun1 "<<a<<setw(10)<<b<<endl; }
void fun2(int& a,int& b) { a=a+b; b=b*2; cout<<"fun2 "<<a<<setw(10)<<b<<endl; }
void fun3(int* a,int* b) { *a=*a+*b; *b=(*b)*2; cout<<"fun3 "<<*a<<setw(10)<<*b<<endl; }
http://wwww.ahtvu.ah.cn/jxc/40vc/student1/wengu/ch6/a6.htm
构造函数的重载和普通函数的重载是相似的,通过构造函数的重载,我们可以创建具有不同初始化值的对象。
1、 默认的构造函数:
• C++ 规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
• 果没有提供一个类的构造函数(一个都未提供),则 C++ 提供一个默认的构造函数,该默认的构造函数是个无参的构造函数,它仅负责创建对象,而不做任何初始化工作。
• 只要一个类定义了一个构造函数(不一定是无参数的构造函数), C++ 就不再提供默认的构造函数了,也就是说,如果为类定义了一个带参数的构造函数,还想要无参构造函数,则必须自己定义。
• 与定义变量类似,在用默认的构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0,否则,对象是随机的。
2、 构造函数的重载:
例 11 :下面程序同时声明了四个构造函数。
#include <iostream.h>
class Tdate
{
public:
Tdate();
Tdate(int d);
Tdte(int m,int d);
Tdate(int m,int d,int y);
Protected:
Int month;
Int day;
Int year;
}
Tdate::Tdate()
{
month=4,day=15;year=2001;
cout<<month<<”/”<<day<<”/”<<year<<endl;
}
Tdate::Tdate(int d)
{
month=4;day=d;year=2001;
cout<<month<<”/”<<day<<”/”<<year<<endl;
}
Tdate::Tdate(int m,int d)
{
month=m;day=d;year=2001;
cout<<month<<”/”<<day<<”/”<<year<<endl;
}
Tdate::Tdate(int m,int d,int y)
{
month=m;day=d;year=y;
cout<<month<<”/”<<day<<”/”<<year<<endl;
}
void main()
{
Tdate aday;
Tdate bday(10);
Tdate cday(2,12);
Tdate dday(1,1,2001);
}
运行结果:
4/15/2001
4/10/2001
1/1/2001
这里需要注意,在构造函数的定义中不能再调用另一个构造函数了,例如,下面是一个错误的构造函数定义:
TdateL::Tdate(int d)
{
Tdate(4,d,2001);
}
在构造函数中,我们可以通过定义并调用一个共享函数初始化对象,也可以通过给构造函数以参数默认值,来为对象初始化。
例如: Tdate 还可以这样来定义:
方法 1 : class Tdate
{
public:
Tdate(){init(4,15,2001);}
Tdate(int d){init(4,d,2001);}
Tdate(int m,int d){init(m,d,2001);}
Tdate{int m,int d,int y}{init(m,d,y);}
Protected:
Int month;
Int day;
Int init(int m,int d,int y)
{
month=m;
day=d;
year=y;
cout<<month<<”/”<<day<<”/”<<year<<endl;
}
};
方法 2 : class Tdate
{
public:
Tdate(int m=4,int d=15,int y=2001)
{
month=m;
day=d;
year=y;
cout<<month<<”/”<<day<<”/”<<year<<endl'
}
protected:
int month;
int day;
int year;
};
???
http://zhidao.baidu.com/question/378472147.html
我的程序是这样的 #include<iostream.h> class TimeType {int h,m,s; public: TimeType(int H,int M,int S); void judge(); void get(){cout<<h<<" "<<m<<" "<<s<<endl;} }; TimeType::TimeType(int H=0,int M=0,int S=0)//初始值置为0,0,0 { h=H; m=M; s=S; } void TimeType::judge() {…… TimeType();//在某些情况下h、m、s为变为初始值 } main() { TimeType T(a,b,c); //a、b、c不全为0 T.get(); T.judge(); T.get(); system("pause"); } 上面经过T.judge()后,无法使h、m、s变为初始值 请问各位 这个问题该如何解决
http://zhidao.baidu.com/question/244355110.html
class Display_class { public: int personname; } 指针: Display_class* m_Display; 中断处: m_Display->personname = 1; 为何?为何?
用new创建对象,new直接返回地址,之后你就通过指针可以访问对象了
Display_class* m_Display; 只定义了指针,并没有创建对象。创建对象要么 Display_class display; 要么 Display_class* pDisplay = NULL; pDisplay = new Display_class; pDisplay->personname = 1; .... delete pDisplay; pDisplay = NULL; 顺便说一下指针最好初始化为NULL,在指针删除之后最好将指针赋值为NULL。
http://zhidao.baidu.com/question/204609864.html
严格意义上的子对象初始化只能在复合类的构造函数的初始化列表中进行。 作为变通,你可以在子对象所属的类中把真正执行初始化工作的代码写成一个普通公开成员函数,在复合类的构造函数体内调用这个函数。 class A{ int data; public: A(){} A(int d):data(d){} void init(int d){data=d;} }; class B{ A a; public: B(int d):a(d)//常规方法,在初始化列表中初始化子对象 { } }; class C{ A a; public: C(int d)//变通方法,在函数体中初始化子对象 { a.init(d); } };http://zhidao.baidu.com/question/102672486.html
一个类的声明是在a.h里 类的函数定义在a.cpp里 这样的话 要调用也应该是#include a.cpp 吗?
参见 http://topic.csdn.net/t/20050722/09/4160766.html#include "a.h" 这样就可以了. 但是要保证编译器可以找到a.cpp文件. 不然,链接的时候会出错,找不到变量或方法的定义.
http://www.cppblog.com/liujiajia/archive/2008/07/14/56131.html
使用引用形参的优点:
在向函数传递大对象时,需要使用引用形参。虽然赋值实参对于内置数据类型的对象或者规模较小的类类型来说没有什么问题,但是对于大部分的类类型或者大型数组,它的效率就比较低了。另外,某些类类型是无法复制的。使用引用形参,函数可以直接访问实参对象,而无须复制它。
示例:
bool isShorter(const string &str1,const string &str2)
{
return str1.size()<str2.size();
}
由于string对象可能非常的长,我们希望避免复制操作。
如果使用引用形参的唯一目的是避免复制形参,则应将形参定义为const引用。
使用引用形参应该注意的:
int incr(int &val)
{
return ++val;
}
void main(void)
{
short v1=1;
const int v2=10;
int v3=20;
incr(v1); //错误,v1不是int
incr(v2); //错误,v2是const
incr(v3); //正确
incr(10); //错误
}
所以,调用非const类型的引用形参,实参必须不是const类型的,而且实参的类型和形参的类型应当一致。
C++ operator关键字(重载操作符)
http://blog.sina.com.cn/s/blog_74a557a60101159f.html
operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名。
这是C++扩展运算符功能的方法,虽然样子古怪,但也可以理解:一方面要使运算符的使用方法与其原来一致,另一方面扩展其功能只能通过函数的方式(c++中,“功能”都是由函数实现的)。
一、为什么使用操作符重载?
对于系统的所有操作符,一般情况下,只支持基本数据类型和标准库中提供的class,对于用户自己定义的class,如果想支持基本操作,比如比较大小,判断是否相等,等等,则需要用户自己来定义关于这个操作符的具体实现。比如,判断两个人是否一样大,我们默认的规则是按照其年龄来比较,所以,在设计person 这个class的时候,我们需要考虑操作符==,而且,根据刚才的分析,比较的依据应该是age。那么为什么叫重载呢?这是因为,在编译器实现的时候,已经为我们提供了这个操作符的基本数据类型实现版本,但是现在他的操作数变成了用户定义的数据类型class,所以,需要用户自己来提供该参数版本的实现。
二、如何声明一个重载的操作符?
A: 操作符重载实现为类成员函数
重载的操作符在类体中被声明,声明方式如同普通成员函数一样,只不过他的名字包含关键字operator,以及紧跟其后的一个c++预定义的操作符。
可以用如下的方式来声明一个预定义的==操作符:
class person{
private:
int age;
public:
person(int a){
this->age=a;
}
inline bool operator == (const person &ps) const;
};
实现方式如下:
inline bool person::operator==(const person &ps) const
{
if (this->age==ps.age)
return true;
return false;
}
调用方式如下:
#include
using namespace std;
int main()
{
person p1(10);
person p2(20);
if(p1==p2) cout<<”the age is equal!”< return 0;
}
这里,因为operator ==是class person的一个成员函数,所以对象p1,p2都可以调用该函数,上面的if语句中,相当于p1调用函数==,把p2作为该函数的一个参数传递给该函数,从而实现了两个对象的比较。
B:操作符重载实现为非类成员函数(全局函数)
对于全局重载操作符,代表左操作数的参数必须被显式指定。例如:
#include
#include
using namespace std;
class person
{
public:
int age;
public:
};
bool operator==(person const &p1 ,person const & p2)
//满足要求,做操作数的类型被显示指定
{
if(p1.age==p2.age)
return true;
return false;
}
int main()
{
person rose;
person jack;
rose.age=18;
jack.age=23;
if(rose==jack)
cout<<"ok"< return 0;
}
C:如何决定把一个操作符重载为类成员函数还是全局名字空间的成员呢?
①如果一个重载操作符是类成员,那么只有当与他一起使用的左操作数是该类的对象时,该操作符才会被调用。如果该操作符的左操作数必须是其他的类型,则操作符必须被重载为全局名字空间的成员。
②C++要求赋值=,下标[],调用(), 和成员指向-> 操作符必须被定义为类成员操作符。任何把这些操作符定义为名字空间成员的定义都会被标记为编译时刻错误。
③如果有一个操作数是类类型如string类的情形那么对于对称操作符比如等于操作符最好定义为全局名字空间成员。
D:重载操作符具有以下限制:
(1) 只有C++预定义的操作符集中的操作符才可以被重载;
(2)对于内置类型的操作符,它的预定义不能被改变,应不能为内置类型重载操作符,如,不能改变int型的操作符+的含义;
(3) 也不能为内置的数据类型定义其它的操作符;
(4) 只能重载类类型或枚举类型的操作符;
(5) 重载操作符不能改变它们的操作符优先级;
(6) 重载操作符不能改变操作数的个数;
(7) 除了对( )操作符外,对其他重载操作符提供缺省实参都是非法的;
E: 注意点
(1)后果载操操作符首先要确定它的返回值是左值,还是右值,如果是左值最返回引用,如果是右值那就直接返回值;
(2) +号等这样的操作符没有对象可以容纳改变后值,对于这样的情况最好返回数值,否则只能要操作符体内创建临时对象用于容纳改变后的值,如果在堆中创建临时对象返回指针或者引用,在操作符函数体外还需要释放它,如果返回的对象而不是引用或者指针,那么效率是比较低的。如果返回的是数值,最好在该类的构造函数中增加对该类型数值的转换函数,如:返回值是int类型,那么最好有一个int类型作为参数的构造函数。
(3)在增量运算符中,放上一个整数形参,就是后增量运行符,它是值返回,对于前增量没有形参,而且是引用返回,示例:
class Test
{
public:
Test(x=3){ m_value = x}
Test &operator ++(); //前增量
Test &operator ++(int);//后增量
private:
Int m_value:
};
Test &Test::operator ++()
{
m_value ++; //先增量
return *this; //返回当前对象
}
Test Test::operator ++(int)
{
Test tmp(*this); //创建临时对象
m_value ++; //再增量
return temp; //返回临时对象
}
(4)因为强制转换是针对基本数据类型的,所以对类类型的转换需自定义;
(5) 转换运行符重载声明形式:operator 类型名();它没有返回类型,因为类型名就代表了它的返回类型,所以返回类型显得多余。
(6)一般来说,转换运算符与转换构造函数(即带一个参数的构造函数)是互逆的,如有了构造函数Test(int),那么最好有一个转换运算符int()。这样就不必提供对象参数重载运算符了,如Test a1(1);Test a2(2); Test a3; a3 = a1+a2;就不需要重载+号操作符了,因为对于a1+a2的运算,系统可能会先找有没有定义针对Test的+号操作符,如果没有,它就会找有没有针对Test类转换函数参数类型的+号操作符(因为可以将+号运行结果的类型通过转换函数转换为Test对象),因为Test类有个int类型的参数,对于int类型有+操作符,所以a1+a2真正执行的是Test(int(a1) + int(a2));即Test(3);
(7)对于转换运算符,还有一个需要注意的地方就是,如果A类中有以B为参数的转换函数(构造函数),那B中不能有A的转换运算符,不然就存在转换的二义性,如:
class A{A(B&){…}}; class B{ operator A(){…}};那么以下语句就会有问题:
B b; A(b);//A(b)有就可能是A的构造函数,也可以是B的转换运算符
程序符号的链接属性:
http://topic.csdn.net/t/20050405/10/3909686.html
模板函数声明和定义均放在.H文件里:
http://topic.csdn.net/t/20050722/09/4160766.html
对象成员的引用:
http://wenku.baidu.com/view/4aa6e520bcd126fff7050b2e.html
参数:
http://wenku.baidu.com/view/b7794a6b011ca300a6c3904a.html
C++ Operator的两种用法:
http://wenku.baidu.com/view/2a96541fa300a6c30d229f04.html
http://topic.csdn.net/u/20100329/21/27c4fe85-370f-42ea-b1c4-837b63dec892.html