繁体   English   中英

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

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

我在某处@classmethod Python中的@classmethod类似于C ++中的静态成员函数。 但是C ++中的等效cls参数是什么?我如何传递它?

下面是一个使用继承和@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()

现在我被困在我不完整的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";
        }
};

如何使用C ++模拟我的Python代码?

return Parent {name}; 是正确的。 但是,静态成员函数不能是const ,因为没有调用它的对象。

在C ++中没有内置的方法来指定“当前类的类型”。 你只需要再写一次Parent 不幸的是,这意味着如果更改类的名称,则还必须更改类的实现中的所有相关事件。

为了模拟您在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();
}

这会产生:

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

这是一个使用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();
}

但是,如果我们从一个干净的石板开始,并希望得到上面的结果。 我们可以写:

#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