运算符2
语法太复杂,有的时候真的要靠区分:: . 和 ->来降低编译器的复杂度 双冒汗是域限定符号,不是同一个东西,就不说了。点和箭头,后面接成员变量,函数,本质上是不太一样的。从语法上来讲,前者是一个变量或者语法糖里的引用,后者是一个指针类型。
::
::是作用域运算符/作用域解析运算符,A::B表示作用域A中的名称B,A可以是名字空间、类、结构;
命名空间及其全局变量和静态变量,类的静态常量变量函数都要用双冒号
"::"在c中表示作用域和所属关系。"::"是运算符中等级最高的,它分为三种,分别如下:
最常见的场景如下:
using std::cout;
int main()
{
int a;
std::cin >> a;
cout << a << std::endl;
return 0;
}
类作用域操作符 “::”指明了成员函数所属的类。如:M::f(s)就表示f(s)是类M的成员函数。 作用域,如果想在类的外部引用静态成员函数,或在类的外部定义成员函数都要用到。使用命名空间里的类型或函数也要用到(如:std::cout, std::cin, std::string 等等)
表示“域操作符” 例:声明了一个类A,类A里声明了一个成员函数void f(),但没有在类的声明里给出f的定义,那么在类外定义f时, 就要写成void A::f(),表示这个f()函数是类A的成员函数。
- 表示引用成员函数及变量,作用域成员运算符 例:System::Math::Sqrt() 相当于System.Math.Sqrt()
基类成员
在某些情况下,希望对虚函数的调用不要进行动态绑定,而是强迫其执行虚函数的某个特定版本。通常情况下,只有成员函数(或友元)中的代码才需要使用。
class Window{
public:
virtual void onResize(){}
};
class SpecialWindow : public Window{
public:
virtual void onResize(){
Window::onResize();
}
};
如果一个派生类虚函数需要调用它的基类版本,但是没有使用作用域运算符,则在运行时该调用将被解析为对派生类自身的调用,从而导致无限递归。
命名空间中使用
namespace my{
void print(){
cout << "namespace" << endl;
}
}
int main()
{
my::print();
return 0;
}
在类中使用
::的前面一般是类名称,后面一般是该类的成员名称,c为例避免不同的类有名称相同的成员而采用作用域的方式进行区分。
例如:A,B表示两个类,在A,B中都有成员member。
A::member就表示类A中的成员member。
B::member就表示类B中的成员member。
在类外定义成员函数
class A{
public:
void funA();
};
void A::funA(){
cout << "A::funA" << endl;
}
class CA{
public:
int va_var;
int add(int a,int b);
int add(int a);
}
// 在实现这个函数必须这样写
int CA::add(int a,int b){
return a + b:
}
// ::也常用于在类变量内部作为当前类实例的的元素进行表示
int CA::add(int a){
return a + ::va_var;
}
覆盖名字查找
当全局变量在局部函数中与其中某个变量重名,那么就可以用::来区
下面的例子中,有一个全局的height变量,但是函数fun的参数把全局的那个height隐藏了,如果我们需要的是外层作用域中的名字,可以显式地通过作用域运算符来进行请求:
int height = 0;
void fun(int height){
cout << height << endl; // 局部
cout << ::height << endl; // 表示全局
}
:
c中,struct与class关键字都用来声明一个类,唯一区别是,前者类成员默认是public,后者类成员默认是private。 类声明后接的冒号代表该类按给定的属性继承自冒号后面的类。
例如: struct A : public B A按public模式继承自B
符号.和->的作用和区别
- 如果是一个对象/引用 调用成员用"."
- 如果是指针对象调用成员函数用"->"
A.B则A为对象或者结构体;点号(.)左边必须为实体。
A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针; 箭头(->)左边必须为指针;
class A
{
public:
int a = 0;
};
int main()
{
A b;
A *p = &b;
b.a; // 类类型的对象访问类的成员
p->a; // 类类型的指针访问类的成员
}