类实例(对象) dot 命名空间 双冒号 非静态函数 [duplicate]

class instance (object) dot namespace double colon non static function [duplicate]

提问人:Tetix 提问时间:10/20/2023 最后编辑:Tetix 更新时间:10/20/2023 访问量:51

问:

#include <iostream>
using namespace std;

namespace xyz {
    class Base {
    public:
        bool configure (double a) {
            cout << "Do nothing. a is currently equal to: " << a << endl;
            return true;
        }
        
        virtual bool update(float& a)=0;
   };  
}

class Child : public xyz::Base {
public:
    virtual bool update(float& a) {
        a = a+0.5;
        cout << "Updated" << endl;
        return false;
    }
};

int main() {
    cout << "Hello World" << endl;
    
    Child median;
    float a = 3.0;
    median.update(a);
    median.xyz::Base::configure(a);
    return 0;
}

我想我在这里错过了一些C++概念。

我完全不知道这条线是怎么回事。这是一个类实例(对象)点一个命名空间::,然后是父类的::表示法,我只用于静态类方法(但甚至不是静态的......median.xyz::Base::configure(a);medianxyzBaseconfigure (double a)

如何解释这甚至工作/编译?

这是我修改的机器人库中的简化 MWE,使其更通用 (https://github.com/ANYbotics/grid_map/blob/master/grid_map_filters/include/grid_map_filters/MedianFillFilter.hpp)

C++ 继承虚拟 扩展

评论

1赞 Ulrich Eckhardt 10/20/2023
您可以使用它来显式指定要调用的一组重写函数中的哪一个。在这种情况下,这是无稽之谈。
0赞 nick 10/20/2023
添加的命名空间让您大吃一惊。这就是您处理对象的基类实例的方式。更常见的方法是制作 configure() 。virtual
0赞 user12002570 10/20/2023
dupe:用于访问基本子对象的作用域解析运算符
0赞 user12002570 10/20/2023
另外,为什么 C++ 需要范围解析运算符?

答:

1赞 NathanOliver 10/20/2023 #1

您在此处看到的是显式调用函数的基类版本。例如,如果您有

namespace xyz {
    
    class Base {
    public:
        bool configure (double a) {
            cout << "Do nothing. a is currently equal to: " << a << endl;
            return true;
        }
        
        virtual bool update(float& a)=0;
   };  
}

class Child : public xyz::Base {
public:
    virtual bool update(float& a) {
        a = a+0.5;
        cout << "Updated" << endl;
        return false;
    }
    bool configure (double a) {
            cout << "In Child::configure. a is currently equal to: " << a << endl;
            return true;
        }
};

int main() {
    cout << "Hello World" << endl;
    
    Child median;
    float a = 3.0;
    median.update(a);
    median.configure(a);
    return 0;
}

然后将打印,因为它正在调用函数的版本。通过使用median.configure(a);In Child::configure. a is currently equal to: 3.5Child

median.xyz::Base::configure(a);

它将改为按现在显式使用函数版本进行打印。您可以在此实时示例中看到输出更改。Do nothing. a is currently equal to: 3.5Base

评论

0赞 Tetix 10/20/2023
我可以看到它是如何用于调用基类函数与子函数的(如果存在的话),但我无法将 median.xyz 作为表示法。如果你也能解决这个问题,请
1赞 NathanOliver 10/20/2023
@Tetix 点的左侧是要使用的对象,右侧是要调用的成员。如果要调用所需的基类函数,则 的基数是median.(xyz::Base::configure)()Childxyz::Baseconfiguremedian.xyz::Base::configure(a);
0赞 463035818_is_not_an_ai 10/20/2023 #2

的全名是 。其方法的全称是 。通常,您不需要或不想显式提及完全限定名称。Base::xyz::Baseconfigure::xyz::Base::configure

例如,当重写方法时,您希望调用该覆盖方法。另一方面,如果出于任何原因,您确实想要调用基类的方法,则可以完全限定该名称。ChildBase

请看这个稍作修改的示例:

#include <iostream>
using namespace std;

struct foo {
    virtual void a() { std::cout << "foo::a\n"; }
};
struct bar : foo {
    void a() { 
        foo::a();
        std::cout << "bar::a\n"; 
    }
};

int main() {
    bar b;
    b.a();
    b.foo::a();
}

输出为:

foo::a
bar::a
foo::a

在内部,我必须调用才能从基类调用该方法,因为 just 会被解析为(并且会有无限递归)。 此外,我还可以通过调用 从基类调用该方法。虽然后者并不典型,但第一种是调用函数的常用方法,否则该函数将被隐藏或无法通过名称解析访问。bar::afoo::aa()bar::amaina.foo::a()