C++基础细节2(二)
外声明,但是最好还是提供一个函数的独立声明,尽量别让程序依赖于编译器。
友元除了可以用于普通的非成员函数,也可以用于类、以及类的成员函数。另外,友元函数不存在传递性。比如说类A中声明了类B是A的友元,类B中声明了类C是B的友元,我们不能仅仅根据这个就认为C是A的友元。也就是说每个类需要自己控制自己的友元类和友元函数。
友元函数可以定义在类的内部。不过就算将友元函数的定义放在类的内部,我们也必须先在函数外面有对这个函数的声明之后才能对这个友元函数进行调用。如下代码:
复制代码
class X
{
friend void f()
{
//函数体
}
X(){ f(); } //error C3861 : “f” : 找不到标识符
void g();
};
void X::g(){ f(); } //error C3861 : “f” : 找不到标识符
void f();
复制代码
如果将f的声明放在类X定义之前就不会报错了。
复制代码
void f();//声明提前
class X
{
friend void f()
{
//函数体
}
X(){ f(); } //编译通过
void g();
};
void X::g(){ f(); } //编译通过
复制代码
可变数据成员:
有些情况下,我们希望能在即使是const成员函数中也能够修改某个数据成员,可以通过在声明变量的时候加上mutable关键字做到这一点:
复制代码
class Screen{
public:
void some_member() const;
void print_count();
private:
mutable size_t count = 0;
};
void Screen::some_member() const
{
++count;
}
void Screen::print_count()
{
cout << count << " ";
}
int main(array ^args)
{
Console::WriteLine(L"Hello World");
Screen item = Screen();
item.print_count();//输出0
item.some_member();
item.print_count();//输出1
}
复制代码
作用域:
如下代码,可以通过类名::成员变量,或者::变量的方式来强制访问
复制代码
int param = 2;
class Scorp
{
public:
void print(int param)
{
cout << param << endl;//形参作用域
cout << Scorp::param << endl;//类中作用域,同this->param
cout << ::param << endl;//类外作用域
}
private:
int param = 1;
};
int main(array ^args)
{
Console::WriteLine(L"Hello World");
Scorp scorp = Scorp();
scorp.print(3);//【param】输出3,【Scorp::param】输出1,【::param】输出2
}
复制代码
转换构造函数:
如果构造函数只接受一个参数,那么存在一种这个类型的隐式转换机制:从构造函数的参数类型向类类型隐式转换。如下代码:
复制代码
class A
{
public:
A(int param)
{
a = param;
}
const void print(const A &item)const
{
cout << item.a << "【注意另一个a】--> " << a << endl;
}
private:
int a;
int b;
int c;
};
int main(array ^args)
{
A a_instance = A(6);
a_instance.print(9);
}
复制代码
输出结果是:9【注意另一个a】--> 6。也就是说,在print函数执行的时候,item.a等于9,a等于6。
注意这里发生了两次构造函数的执行,第一次是定义a_instance并且初始化的时候这时候param为6;第二次是调用a_instance.print(const A &item)函数的时候,特别要注意的是:这里的形参是一个常量引用,因此这里可以使用隐式转化机制,传入A的单个参数的构造函数的形参(整型),用这个方式来隐式处理:编译器通过给定的int型的9自动调用对应的构造函数创建了一个A类型的对象,生成的这个临时对象传给了print函数,并且作为item在函数体中使用,自然item.a的值就是9。
另外要注意的是这里我们的参数使用的int这个内置类型,所以处理的时候能够使用print(9)这种字面量形式的参数。如果构造函数的唯一参数不是内置类型,是其它的比如string,那么这里在处理的时候就不能直接写成print("9"),而是要分成两句书写:
string str="9";
a_instance.print(str);
原因是在这种非内置类型的使用的时候,传入的是"9",实际上会调用string的默认构造函数string("9")进行一次转换,而类类型的转换只允许进行一次。int这样的内置类型则没有所谓的默认构造转换的操作。
上面的书写我们也可以合起来写成a_instance.print(string("9"))