C++ 中的 "::" "." 和 "->" 有什么区别
What is the difference between "::" "." and "->" in c++
我创建了一个名为Kwadrat
的类。该类有三个int
字段。我的开发环境建议我通过 ::
& ->
运算符访问Kwadrat
创建对象的字段。我尝试了这两个运算符,发现->
运算符能够成功访问对象字段中的数据,尽管对于->
运算符来说并非如此。我还发现.
运算符也将访问类成员。我很困惑,不明白为什么有三个成员用于访问对象成员和/或方法。有人可以向我解释一下这三个运算符之间的区别吗?
1. ->
2. ::
3. .
<小时 />
#include <iostream>
using namespace std;
class Kwadrat{
public:
int val1,
val2,
val3;
Kwadrat(int val1, int val2, int val3)
{
this->val1 = val1; // Working
this.val2 = val2; // Doesn't Work!
this::val3 = val3; // Doesn't Work!
}
};
int main()
{
Kwadrat* kwadrat = new Kwadrat(1,2,3);
cout<<kwadrat->val1<<endl;
cout<<kwadrat->val2<<endl;
cout<<kwadrat->val3<<endl;
return 0;
}
1.->
用于通过pointer
访问对象成员变量和方法
Foo *foo = new Foo();
foo->member_var = 10;
foo->member_func();
2. 通过对象instance
访问对象成员变量和方法的.
Foo foo;
foo.member_var = 10;
foo.member_func();
3. ::
用于访问class/struct
或namespace
的静态变量和方法。它还可用于从另一个作用域访问变量和函数(在这种情况下,类、结构、命名空间实际上是作用域)
int some_val = Foo::static_var;
Foo::static_method();
int max_int = std::numeric_limits<int>::max();
在C++中,您可以使用不同的运算符访问字段或方法,具体取决于其类型:
- 类名::字段
- 名:类公共静态字段和方法
- ClassInstance.FieldName :通过类引用访问公共字段(或方法)
- 类指针->字段名称:访问公共字段(或方法)取消引用类指针
请注意,:: 应该与类名而不是类实例一起使用,因为静态字段或方法对于类的所有实例都是通用的。
class AClass{
public:
static int static_field;
int instance_field;
static void static_method();
void method();
};
然后,您可以通过以下方式访问:
AClass instance;
AClass *pointer = new AClass();
instance.instance_field; //access instance_field through a reference to AClass
instance.method();
pointer->instance_field; //access instance_field through a pointer to AClass
pointer->method();
AClass::static_field;
AClass::static_method();
很简单::
是范围运算符,.
是访问运算符(我忘记了实际名称是什么?),->
是取消引用箭头。
::
- 限定函数的范围。也就是说,它让编译器知道函数位于哪个类中,从而知道如何调用它。如果使用此运算符调用函数,则该函数是static
函数。
.
- 这允许访问已创建对象上的成员函数。例如,Foo x; x.bar()
调用方法bar()
在类型为 Foo
的实例化对象x
。您还可以使用它来访问公共类变量。
->
- 本质上与.
相同,只是这适用于指针类型。本质上,它取消引用指针,而不是调用.
。使用它等效于(*ptr).method()
您有一个指向对象的指针。因此,您需要访问指针指向的对象字段。要取消引用您使用的指针*
并访问字段,请使用 .
,因此可以使用:
cout << (*kwadrat).val1;
请注意,括号是必需的。这个操作很常见,很久以前(当C还年轻的时候),他们决定创建一个"速记"方法来做到这一点:
cout << kwadrat->val1;
它们被定义为相同。如您所见,->
基本上只是将*
和.
组合到单个操作中。如果您直接处理对象或对对象的引用,则可以使用该.
而无需先取消引用指针:
Kwadrat kwadrat2(2,3,4);
cout << kwadrat2.val1;
::
是范围解析运算符。当您只需要限定名称,但根本不处理单个对象时,会使用它。这主要用于访问静态数据成员:
struct something {
static int x; // this only declares `something::x`. Often found in a header
};
int something::x; // this defines `something::x`. Usually in .cpp/.cc/.C file.
在这种情况下,由于x
是static
,因此它不与something
的任何特定实例相关联。事实上,即使没有创建该类型对象的实例,它也会存在。在这种情况下,我们可以使用范围解析运算符访问它:
something::x = 10;
std::cout << something::x;
但请注意,它也允许访问静态成员,就好像它是特定对象的成员一样:
something s;
s.x = 1;
至少如果没记错的话,在C++历史的早期,这是不允许的,但意思是明确的,所以他们决定允许它。
运算符具有相关但不同的含义,尽管 IDE 提供了误导性说明。
::
运算符称为范围解析运算符,用于从命名空间或类获取到其成员之一。
.
和->
运算符用于访问对象实例的成员,只有在创建对象实例后才会发挥作用。如果有一个实际对象(或对该对象的引用,在声明的类型中用 &
声明),则使用 .
;如果有一个指向对象的指针(在声明的类型中使用 *
声明),则使用 ->
。
this
对象始终是指向当前实例的指针,因此 ->
运算符是唯一有效的运算符。
例子:
// In a header file
namespace Namespace {
class Class {
private:
int x;
public:
Class() : x(4) {}
void incrementX();
};
}
// In an implementation file
namespace Namespace {
void Class::incrementX() { // Using scope resolution to get to the class member when we aren't using an instance
++(this->x); // this is a pointer, so using ->. Equivalent to ++((*this).x)
}
}
// In a separate file lies your main method
int main() {
Namespace::Class myInstance; // instantiates an instance. Note the scope resolution
Namespace::Class *myPointer = new Namespace::Class;
myInstance.incrementX(); // Calling a function on an object instance.
myPointer->incrementX(); // Calling a function on an object pointer.
(*myPointer).incrementX(); // Calling a function on an object pointer by dereferencing first
return 0;
}
-> 表示指向类实例的指针
. 用于类实例
:: 用于类名 - 例如,使用静态成员时
'::' 用于静态成员。
其他人已经回答了不同的语法,但请注意,当你做你的couts
时,你只使用->
:
int main()
{
Kwadrat* kwadrat = new Kwadrat(1,2,3);
cout<<kwadrat->val1<<endl;
cout<<kwadrat->val2<<endl;
cout<<kwadrat->val3<<endl;
return 0;
}
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 什么时候调用组成单元对象的析构函数
- #定义c-预处理器常量..我做错了什么
- 努力将整数转换为链表。不知道我在这里做错了什么
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 什么时候在C++中返回常量引用是个好主意
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- C++避免重复声明的语法是什么
- c++库的公共头文件中应该包含什么
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- ifstream什么都没读
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 什么是模板&lt;&gt;inline bla bla
- 使用 std::vector<boost::shared_ptr<Base_Class>> 或 boost::p tr_vector 的性能注意事项是什么<Base>