2016-10-31 17 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