C++ 双冒号作用域转换操作符使用双冒号操作符 (::) 可以用以下名称限定具有全局作用域的 C++ 成员函数、顶级函数或变量:
- 重载名(不同参数类型使用同一名称)
- 二义名(不同类中使用同一名称)
VC中双冒号(::)的作用::是C++里的“作用域分解运算符”。比如声明了一个类A,类A里声明了一个成员函数voidf(),但没有在类的声明里给出f的定义,那么在类外定义f时,就要写成voidA::f(),表示这个f()函数是类A的成员函数。 :: 一般还有一种用法,就是直接用在全局函数前,表示是全局函数。当类的成员函数跟类外的一个全局函数同名时,考试,大提示在类内定义的时候,打此函数名默认调用的是本身的成员函数;如果要调用同名的全局函数时,就必须打上::以示区别。比如在VC里,你可以在调用API函数时,在API函数名前加::。
//---------------------------------------更新
如果一个类没有写构造函数和析构函数并不会自动生成额外的构造函数或析构函数,除非:
(1)它所继承的父类函有构造函数或析构函数,这时子类会产生默认的构造函数和析构函数
以调用父类的构造函数和析构函数。
或
(2)它的成员中含有具有构造函数或析构函数类的对象。这时会产生构造函数及析构函数来创建及析构该成员。
另:声明不一样,编译器有的时候会提供默认构造函数
//----------------------------------------更新
类里面的数据成员,加上mutable后,修饰为 const的成员函数就可以修改它了
比如有一个类
class A
{
...
void func1() const //声明为 const
{
//在这里不能修改类的私有成员变量 a
//因为函数 func1 声明为 const
}
private:
int a;
}
但是在某些情况下,要修改 a ,但又不想改变 func1 的 const 属性
所以只好把 a 声明为 mutable
这样在 func1 里也可以访问修改 a 的值了
---------------------------------------------------------
常函数:
假如在前面定义了一个Student类,则:
Student const stu;
stu就是一个常对象,对于常对象,不能通过常对象调用Student类中定义的普通函数成员,只能调用类中常函数成员。而且常函数成员中也不能调用类的其他普通函数成员,可以引用类的普通的数据成员,但不能更新对象的数据成员。
//----------------------------------------------------------更新
关于操作符的重载 一、不可以被重载的操作符
1.域操作符::
2.取成员指针操作符.*
3.成员操作符.
4.选择操作符?:
二、重载操作符必须有一个类类型操作数
用于内置类型的操作符,其含义不能改变,也不能为内置类型定义新的操作符。
三、重载的操作符的优先级、结合性或操作数数目都不能改变。除了函数调用操作符operator()之外,重载操作符时使用默认实参是非法的。
四、重载操作符并不能保证操作数的求值顺序
逻辑与(&&)、逻辑或(||)经重载后没有短路求值特性
逗号(,)经重载后也不保证从左到右依次计算
五、重载操作符可以定义为类成员函数或普通的非成员函数
类成员函数有一隐含的this指针参数
六、操作符重载为普通非成员函数时,通常须将其声明为所操作类的友元。
重载操作符的设计
1.不要重载具有内置含义的操作符
赋值操作符(=)、取地址操作符(&)、逗号操作符(,)对类类型有默认含义:合成的赋值操作符进行逐个成员赋值;取地址操作符返回对象地址;逗号操作符从左到右计算每个表达式的值,并返回最右边操作数的值。
2.大多数操作符对类对象没有意义
除非提供了了重载定义,赋值操作符(=)、取地址操作符(&)、逗号操作符(,)对类类型操作数没有定义。
3.若一个类有算数操作符或位操作符,则提供相应的复合赋值操作符是好的做法。
4.用作关联容器的健类型的类应该定义小于操作符(<);用作顺序容器元素类型的类应该定义相等操作符(==)、小于操作符(<)
5.选择成员或非成员实现
(1)赋值操作符(=),下标操作符([]),函数调用操作符(()),指针成员访问箭头(->)必须重载为类成员函数。
(2)复合赋值操作符应定义为类成员函数;但定义为非成员函数也不会出线编译错误。
(3)改变对象状态或与给定类型紧密联系的操作符应定义为类成员。如自增操作符(++)、自减操作符(--)应定义为类成员。
(4)对称的操作符如算术操作符、相等操作符、关系操作符和位操作符应定义为非成员。
//-------------------------------------------------------------更新
C++拷贝构造函数的几个细节 原创作者: grantren 阅读:132次 评论:1条 更新时间:2007-01-05
Link http://www.javaeye.com/wiki/CPP/811-C++拷贝构造函数的几个细节
拷贝构造函数是C++最基础的概念之一,大家自认为对拷贝构造函数了解么?请大家先回答一下三个问题:
1. 以下函数哪个是拷贝构造函数,为什么?
X::X(const X&); - X::X(X); X::X(X&, int a=1);
- X::X(X&, int a=1, b=2); 2. 一个类中可以存在多于一个的拷贝构造函数吗?
3. 写出以下程序段的输出结果, 并说明为什么?如果你都能回答无误的话,那么你已经对拷贝构造函数有了相当的了解。
#include - #include
- struct X { template<typename T>
- X( T& ) { std::cout << "This is ctor." << std::endl; }
- template<typename T> X& operator=( T& ) { std::cout << "This is ctor." << std::endl; }
- };
- void main() { X a(5);
- X b(10.5); X c = a;
- c = b; }
解答如下:
1. 对于一个类X,如果一个构造函数的第一个参数是下列之一:
a) X&
b) const X&
c) volatile X&
d) const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.
X::X(const X&); //是拷贝构造函数 - X::X(X&, int=1); //是拷贝构造函数 2.类中可以存在超过一个拷贝构造函数,
class X { - public: X(const X&);
- X(X&); // OK }; 注意,如果一个类中只存在一个参数为X&的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化.
class X { - public: X();
- X(X&); };
- const X cx;
- X x = cx; // error 如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数.
这个默认的参数可能为X::X(const X&)或X::X(X&),由编译器根据上下文决定选择哪一个.
默认拷贝构造函数的行为如下:
默认的拷贝构造函数执行的顺序与其他用户定义的构造函数相同,执行先父类后子类的构造.
拷贝构造函数对类中每一个数据成员执行成员拷贝(memberwise Copy)的动作.
a)如果数据成员为某一个类的实例,那么调用此类的拷贝构造函数.
b)如果数据成员是一个数组,对数组的每一个执行按位拷贝.
c)如果数据成员是一个数量,如int,double,那么调用系统内建的赋值运算符对其进行赋值.
3. 拷贝构造函数不能由成员函数模版生成.
struct X { - template<typename T> X( const T& ); // NOT copy ctor, T can't be X
- template<typename T>
- operator=( const T& ); // NOT copy ass't, T can't be X };
- 原因很简单, 成员函数模版并不改变语言的规则,而语言的规则说,如果程序需要一个拷贝构造函数而你没有声明它,那么编译器会为你自动生成一个. 所以成员函数模版并不会阻止编译器生成拷贝构造函数, 赋值运算符重载也遵循同样的规则.(参见Effective C++ 3edition, Item45)
//-------------------------------------------------------------------更新
const char* XXXX::why()const{return "test"}; 这种写法, 这里第一个const表示函数why的返回值是个常量指针, 第二个const表示why是个常量函数, 即不会改XXXX的成员. const就是只读之意也!