2014-09-23 28 views
1

我有一個抽象基類和從這個基類派生的一對類。我想介紹一個static const成員,它在兩個派生類之間具有不同的值,但對於給定的派生類的所有實例具有相同的值。聲明抽象基類中的靜態常量成員,將它賦值給派生類中的值?

我有代碼使用分配給兩個派生類之一的實例的基類指針,這樣我就可以通過更改指派給基類指針的派生類之間輕鬆切換。我希望能夠以類似的方式使用基類獲取派生類的常量值的值,以便我可以輕鬆地在兩個類之間切換。期望的行爲看起來是這樣的:

#include <iostream> 
using namespace std; 

// Abstract base class 
class A { 
    protected: 
    int c; // this is really a constant and should also be static 
    public: 
    static int s; 
    int get_c() const { 
     return this->c; 
    } 
    virtual int foo() = 0; // makes this class abstract 
}; 

class B : public A { 
    public: 
    static const int sb = 10; 
    B() { 
     this->c = 1; 
    } 
    int foo() { 
     return -1; 
    } 
}; 

class C : public A { 
    public: 
    static const int sc = 20; 
    C() { 
     this->c = 2; 
    } 
    int foo() { 
     return -2; 
    } 
}; 

int main() { 
    B btest; 
    C ctest; 

    A *ptr = &btest; // pointer to instance of B 
    //cout << ptr->c << endl; // would fail compilation (c is protected) 
    cout << "B's c = " << ptr->get_c() << endl; 
    cout << "B's foo() returns " << ptr->foo() << endl; 
    cout << "Accessing B's static const member: " << B::sb << endl; 

    ptr = &ctest; // pointer to instance of C 
    //cout << ptr->c << endl; // would fail compilation (c is protected) 
    cout << "C's c = " << ptr->get_c() << endl; 
    cout << "C's foo() returns " << ptr->foo() << endl; 
    cout << "Accessing C's static const member: " << C::sc << endl; 

    return 0; 
} 

在上面的代碼sbscstatic const會員我想要的,但他們的問題是基類A沒有他們的知識。基類成員c正在做我想要的,但不是static const根據需要(我做了c一個protected成員,以便它不能被修改,但如果我可以宣佈它const那麼它可以是public)。此代碼具有從c所需的行爲:

  1. 我可以得到鮮明的值c從使用基類指針每個派生類。
  2. c是有效的,因爲它是protected,我沒有提供setter功能。

然而,c是不是真的不斷在它不是const,它不是那麼static每個實例有它的一個不必要的副本。

有沒有辦法得到想要的行爲,還宣佈cstatic constsbsc

+0

我不明白這個問題,如果你想爲每個派生c一個不同的值,那麼它不能是靜態的。如果需要修改,那麼它不能是const。如果關注只是訪問,那麼你可以在基類中將其隱藏起來,並在必要時提供公共getter/setter?如果這不是你的意思,你能否改寫成具體的問題? – skimon 2014-09-23 16:36:58

+0

它不需要修改,並且對於給定的派生類的每個實例它都是相同的值。但對於每個不同的派生類來說它是一個不同的值。 – Null 2014-09-23 16:39:58

+0

這聽起來像是一個X/Y問題。你能告訴我們爲什麼你需要這個嗎? – Borgleader 2014-09-23 16:40:33

回答

4

您無法在A中使用靜態變量實現此功能;這對A的所有亞型都是共同的,所以你不能爲每個亞型獲得不同的值。由於只有在運行時才知道基類指針後面的動態類型,因此需要一個運行時機制來從中獲取值。

如果在構造初始化它這可以使用針對每個對象變量,其可以是const

class A { 
    // ... 
    const int c; 
    A(int c) : c(c) {} 
}; 

class B : public A { 
    // ... 
    B() : A(1) {} 
}; 

class C : public A { 
    // ... 
    C() : A(2) {} 
}; 

或每個子類重寫返回不同的值的虛擬功能:

class A { 
    // ... 
    int get_c() const = 0; 
}; 

class B : public A { 
    // ... 
    int get_c() const {return 1;} 
}; 

class C : public A { 
    // ... 
    int get_c() const {return 2;} 
}; 

兩種選擇都符合您的要求;一個具有訪問虛擬函數調用的代價,另一個具有每個對象變量的代價。您必須決定哪些費用更適合您的需求。

+0

是的,這將工作。我只是看起來像一個函數調用,只是爲了返回一個在編譯時已知的值,並且從不改變是無意義的開銷。 – Null 2014-09-23 16:50:54

+0

@Null:在編譯時不知道,因爲它取決於它所調用的對象的運行時類型。 – 2014-09-23 16:51:58

+0

好點。我認爲它在編譯時是已知的,因爲我只將基類指針賦值給兩個派生類之一的實例 - 如果我切換到不同的派生類,則修改源並重新編譯。我只有幾個派生類的實例,所以我認爲'const'成員方法對我的目的更好 - 額外的空間需求並不是什麼大問題。謝謝。 – Null 2014-09-23 17:04:01

相關問題