双结肠混乱

Double Colon confusions

本文关键字:混乱      更新时间:2023-10-16

为什么我可以在未定义的函数和类中使用双冒号,但我不能在变量中使用?

例:

#include <iostream>
using namespace std;
class Person{
public:
int age;
string name();
};
int Person::age = 10; //It outputs an error
string Person::name(){ //It doesn't
return "n";
}

为什么我可以在未定义的函数和类中使用双冒号,但我不能在变量中使用?

age是一个实例字段,但它存在于内存中的多个位置 - 每个存在的Person一个。

现在,我将详细介绍::运算符的作用、如何使用它以及类成员与实例成员的比较static

::运算符:

::(范围解析运算符)在C++有多种用途:

如果你熟悉Java,C#或JavaScript,那么它可以比作点取消引用或"导航运算符".(例如namespace.Class.Method().Result) - 除了C++使用不同的运算符进行不同类型的导航和取消引用:

  • .成员访问运算符,类似于 C - 它仅适用于"对象值"和引用 (foo&),不适用于指针 (foo*)。
  • ->是指针类型的另一个成员访问运算符,请注意,可以重写此运算符,但不能重写.运算符(重写->是有风险的,但如果正确完成,它可以改善智能指针库的人体工程学)。
  • ::范围解析运算符- 它有几个不同的用途:
    • 命名空间导航 - Java 和 C# 使用.来导航包和命名空间,而 C++ 使用::,例如:using std::time
    • 当不限定时,它也用于引用全局命名空间,例如::std如果您正在编写已经在命名空间中的代码,这很方便。
    • 它还用于访问类型的静态成员 - 通常是实际的static成员(静态方法或字段),但也包括enum class(作用域枚举)值等项(例如SomeEnumClass::value_name)
    • 最后,它还用于在处理virtual方法实现时选择特定的基方法:当重写的方法需要在超类中调用基实现时使用 - C++没有 C# 和 Java 具有的单数basesuper关键字(分别),因为C++允许多重继承,因此必须指定特定的父类名: 如何从派生类函数调用父类函数?

无论如何,在您的情况下,您似乎对实例和静态成员的实际含义感到困惑,因此这里有一个插图:

class Person {
public:
int height; // each Person has their own height, so this is an instance member
static int averageHeight; // but an individual Person doesn't have an "average height" - but a single average-height value can be used for all Persons, so this is a shared ("static") value.
int getAverageHeight() { // this is an instance method, btw
return Person::averageHeight; // use `Person::` to unambiguously reference a static member of `Person`
}
Person()
: height(0) {
// instance members should be initialized in the constructor!
}
}
// This will create an array of 10 people (10 different object instances).
// Each Person object (an instance) will have its own `height` in memory
Person* multiplePeople = new Person[10];
// btw, you probably should use `std::array` with an initializer instead:
// array<Person,10> multiplePeople{}; // <-- like this
// This sets a value to the `staticField` member, which exists only once in memory, that is, all Person instances share the same value for this member...
Person::averageHeight = 175; // 175cm
// ...for example:
assert( 175 == multiplePeople[3]->getAverageHeight() );
assert( 175 == multiplePeople[6]->getAverageHeight() );
// However instance members can have different values for each instance:
multiplePeople[3]->height = 170;
multiplePeople[6]->height = 180;
// Btw `height` is initialized to 0 in each Person's constructor.
assert( 170 != multiplePeople[0]->height );
assert( 180 != multiplePeople[7]->height );