简体   繁体   English

如何在C ++中的类中使用static关键字来模拟Python中@classmethod的行为?

[英]How do I use static keyword inside class in C++ to emulate the behavior of @classmethod in Python?

I read somewhere that @classmethod in Python is similar to static member function in C++. 我在某处@classmethod Python中的@classmethod类似于C ++中的静态成员函数。 But what is the equivalent cls parameter in C++ and how do I pass it? 但是C ++中的等效cls参数是什么?我如何传递它?

Below is a Python code that uses inheritance and @classmethod , 下面是一个使用继承和@classmethod的Python代码,

class Parent():
    def __init__(self, name):
        self._name = name
    @classmethod
    def produce(cls, name):
        return cls(name)
    def say_my_name(self):
        print("I am parent", self._name)

class Child(Parent):
    def say_my_name(self):
        print("I am child", self._name)

p1 = Parent("One")
p1.say_my_name()
p2 = Parent.produce("Two")
p2.say_my_name()

p1 = Child("One")
p1.say_my_name()
p2 = Child.produce("Two")
p2.say_my_name()

And now I am stuck in my incomplete C++ code as follows 现在我被困在我不完整的C ++代码中,如下所示

class Parent
{
    protected:
        std::string name;
    public:
        Parent(const std::string& name): name{name} {};

        // Can I not use static in the next statement?
        // Parent is already hard-coded, what's the cls in C++?
        static Parent produce(const std::string& name) const
        {
            return Parent {name};
        }
        void say_my_name() const
        {
            std::cout << "I am parent " << name << "\n";
        }
};

How can I emulate my Python code using C++? 如何使用C ++模拟我的Python代码?

return Parent {name}; is correct. 是正确的。 However, a static member function cannot be const , since there is no object on which it is called. 但是,静态成员函数不能是const ,因为没有调用它的对象。

There is no built-in way to specify "the type of the current class" in C++. 在C ++中没有内置的方法来指定“当前类的类型”。 You just have to write Parent again. 你只需要再写一次Parent Unfortunately, that means that if you change the name of the class, you also have to change all relevant occurrences in the class's implementation. 不幸的是,这意味着如果更改类的名称,则还必须更改类的实现中的所有相关事件。

In order to emulate the use case you demonstrate in the Pynthon code some repetition is required: 为了模拟您在Pynthon代码中演示的用例,需要重复一些:

#include <iostream>
#include <string>

class Parent
{
protected:
    std::string name;
public:
    Parent() = default;
    Parent(const std::string& name) : name{name} {};
    using cls = Parent; // this isn't normally done, normally Parent is just repeated

    // Can I not use static in the next statement?
    // Parent is already hard-coded, what's the cls in C++?
    //static Parent produce(const std::string& name) const
    cls produce(const std::string& name) const // static would mean the function does not belong to any object, so it must be removed if we want to call it on a temporary const object
    {
        return cls{name};
    }

    void say_my_name() const
    {
        std::cout << "I am parent " << name << "\n";
    }
}; 

class Child : public Parent {
public:
    using cls = Child; // this isn't normally done, normally Child is just repeated

    Child() = default;
    Child(const std::string& name) : Parent{name} {};

    void say_my_name() const
    {
        std::cout << "I am child " << name << "\n";
    }

    cls produce(const std::string& name) const  // have to repeat produce() here so that it hides Parent::produce().
    {
        return cls{name};
    }
};

int main()
{
    auto p1 = Parent("One");
    p1.say_my_name();
    auto p2 = Parent().produce("Two");
    p2.say_my_name();

    auto c1 = Child("One");
    c1.say_my_name();
    auto c2 = Child().produce("Two");
    c2.say_my_name();
}

This produces: 这会产生:

I am parent One
I am parent Two
I am child One
I am child Two

Here is a slightly modified version that uses static : 这是一个使用static的略微修改的版本:

#include <iostream>
#include <string>

class Parent
{
protected:
    std::string name;
public:
    Parent(const std::string& name) : name{name} {};
    using cls = Parent; // this isn't normally done, normally Parent is just repeated

                        // Can I not use static in the next statement?
                        // Parent is already hard-coded, what's the cls in C++?
                        //static Parent produce(const std::string& name) const
    static cls produce(const std::string& name) // here const would not make sense, this function will not be called on a particular instance of Parent
    {
        return cls{name};
    }

    void say_my_name() const
    {
        std::cout << "I am parent " << name << "\n";
    }
};

class Child : public Parent {
public:
    using cls = Child; // this isn't normally done, normally Child is just repeated

    Child(const std::string& name) : Parent{name} {};

    void say_my_name() const
    {
        std::cout << "I am child " << name << "\n";
    }

    static cls produce(const std::string& name) // have to repeat produce() here so that it hides Parent::produce().
    {
        return cls{name};
    }
};

int main()
{
    auto p1 = Parent("One");
    p1.say_my_name();
    auto p2 = Parent::produce("Two"); // No instance of Parent is used to create p2
    p2.say_my_name();

    auto c1 = Child("One");
    c1.say_my_name();
    auto c2 = Child::produce("Two");
    c2.say_my_name();
}

If however, we were to start from a clean slate, and wanted the result above. 但是,如果我们从一个干净的石板开始,并希望得到上面的结果。 We could write: 我们可以写:

#include <iostream>
#include <string>

class Parent
{
protected:
    std::string name;
public:
    Parent(const std::string& name) : name{name} {};

    void say_my_name() const
    {
        std::cout << "I am parent " << name << "\n";
    }
}; 

class Child : public Parent {
public:
    Child(const std::string& name) : Parent{name} {};

    void say_my_name() const
    {
        std::cout << "I am child " << name << "\n";
    }
};

template <typename T>
T produce(const std::string& name)
{
    return{name};
}

int main()
{
    Parent p1{"One"};
    p1.say_my_name();
    auto p2 = produce<Parent>("Two");
    p2.say_my_name();

    Child c1{"One"};
    c1.say_my_name();
    auto c2 = produce<Child>("Two");
    c2.say_my_name();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM