2016-10-31 18 views
3

我在Python的某处读到@classmethod类似于C++中的静态成员函数。但C++中的等效cls参数是什么?我如何传递它?如何在C++类中使用static关键字来模拟Python中@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() 

,现在我停留在我的不完整的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代码++ ?

+0

“但是什么是C++中等价的'cls'参数” - 没有等价的。 – user2357112

回答

1

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

美丽,只有一个问题,当你使用模板,你写了'return {name};'而不是'return T {name};'(我从来没有见过这个) '{}'作为类“T”的构造函数中的参数? – Nicholas

+0

@Nicholas'return {name};'使用[list-initialization](http://en.cppreference.com/w/cpp/language/list_initialization)初始化[returned](http://en.cppreference。 com/w/cpp/language/return)对象。 – wally

3

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

在C++中没有内建的方式来指定“当前类的类型”。你只需要再次写Parent。不幸的是,这意味着如果你改变了这个类的名字,你还必须改变该类实现中的所有相关事件。

+0

我目前对'const'函数的理解是它使'const'类对象能够调用它,这很重要,因为我们通常将类对象作为'const'引用传递。那么你是否暗示我们无法通过const类对象调用'static produce()'?或者它只是一个C++规则,每当使用静态成员函数时,不需要'const'?我的第二个问题是,如果我们必须再次编写'Parent',那么我们可能不能继承'produce()'函数,并且必须重新定义'Child'类中的'produce()',这也是你的观点吗?你如何用C++编写?谢谢。 – Nicholas

+0

@Nicholas当你调用一个静态成员函数时,没有对象实例。 – Brian