2016-04-14 37 views
1

如果我有一個基類A我希望能夠在使用數組我希望能夠有一個,其大小由它的孩子請問C++支持抽象數組長度

確定A編寫代碼指針數組A,但我不希望有用於每個長度

創建一個單獨的成員函數的最佳我能想出如下:

class A 
{ 
    char type; 
    int * values; 
    int calc(int pos); // implementation is not relevant to question 
public: 
    A (int * arr) : values(arr) {} 
    int foo(int pos) 
    { 
     int index=calc(pos); 
     return values[index]; 
    } 
}; 

template <size_t X> 
class B : public A 
{ 
    int vals[X]; 
public: 
    B() : A(vals) {} 
}; 

template<> 
class B<0>; // don't want 0 allowed 

這允許訪問一個數組在哪裏的孩子確定大小,並且它是連續的內存

但是,它浪費了values指針的空間,並且模糊了編譯器可能用於優化的信息,因爲實現它不一定是孩子通過構建的連續內存,但我想要求連續記憶。

理想我想用直接在A

偏移在C這個工程爲int values[],但沒有C++相當於

+1

能的基類是模板? –

+2

代碼是錯誤的。指向數組的指針不是**指向它的數據類型的指針! – SergeyA

+9

[std :: vector ](http://www.cplusplus.com/reference/vector/vector/)可能嗎? – Weston

回答

-2

對於剛剛改變對象的數組的大小的基本能力,你正如Fred Larson指出的那樣,可能會尋找模板。其實很簡單...

template <const int arraySize> 
class MyClass 
{ 
    private: 
     int vals[arraySize]; 
} 

在這一點上,你甚至不需要任何派生類。你很好去,並可以與任何大小在飛行。

但請記住,MyClass在這種情況下不是有效的類型。因爲這是一個模板,所以你必須指定大小。

MyClass wrong; //This will throw an error. MyClass is not a type. 
MyClass<64> right; //This is a proper use of the type. 

如果您需要儲存不同大小的那些對象的附加功能,你可以繼承很容易使用虛擬[但不是抽象的]基類結合這一點。

(請忽略這些混沌的設計,因爲我還沒有費心去定義在這個例子中我的構造函數/析構函數)。

class BaseClass 
{ 
    public: 
     BaseClass(){} 
     virtual int access(int i) 
     { 
      return 0; 
     } 
     virtual ~BaseClass(){} 
}; 

template <const int arraySize> 
class MyClass : public BaseClass 
{ 
    public: 
     MyClass(){} 
     int access(int i) 
     { 
      return vals[i]; 
     } 
     ~MyClass(){} 
    private: 
     int vals[arraySize]; 
}; 

警告:這是很關鍵的基礎不能是抽象的如果你想能夠將你的派生類存儲在一個向量中。見this question

在這個例子中,當然,你可能想要創建包裝函數來訪問數組。

+0

我已編輯,以滿足額外的需求。對不起,忽略了。 – CodeMouse92

2

實現這個經典的方法是使用繼承和虛擬成員

class A { 
    virtual int& value_at(size_t pos); 
    // other interesting methods 
}; 

// subclass of A that uses std::vector for storage 
class B: public A { 
    std::vector<int> storage; 
    int& value_at(size_t pos) { 
     return storage[pos]; 
    } 
}; 

// subclass of A that uses a fixed-size array for storage 
template<int N> 
class C: public A { 
    int storage[N]; 
    int& value_at(size_t pos) { 
     return storage[pos]; 
    } 
}; 

B b;  // ...initialize b... 
C<10> c; // ...initialize c... 
A *a1 = &b; 
A *a2 = &c; 
// call a1->value_at(), a2->value_at() to access arrays 
// transparently, regardless of storage (along with other 
// public methods of A). 

這種方法需要A::value_at通過一個虛擬表或等同機制調度。如果在存儲策略將被用於該編譯時已知的,可以使A模板類:

template<typename T> 
class A: public T { 
    // other interesting methods, that use value_at() from T 
}; 

class vec_storage { 
    std::vector<int> storage; 
public: 
    int& value_at(size_t pos) { 
     return storage[pos]; 
    } 
}; 

// subclass of A that uses a fixed-size array for storage 
template<int N> 
class array_storage { 
    int storage[N]; 
public: 
    int& value_at(size_t pos) { 
     return storage[pos]; 
    } 
}; 

A<vec_storage> b; 
A<array_storage<10>> c; 

在這個例子中,bc將不會在運行時的額外的間接執行,但在沒有泛型基類的成本,所以期望A &的函數不能傳遞給bc的引用。

+0

經典我不同意,因爲這相當低效。問題中的設計更具性能。 – MSalters

+0

@MSalters它更高性能,但不符合(規定的)要求 - 子類可能實現非連續存儲。 – user4815162342

+0

我試圖在最後重申那部分,目標是分配連續存儲 –

3

當然可以,使用模板:

template<std::size_t size> 
struct A { 
    A(std::array<int, size> _values) : values{_values} {} 

private: 
    std::array<int, size> values; 
}; 

struct B : A<4> { 
    using A<4>::A; 
}; 

然後,你可以使用你的類是這樣的:

B myB{5, 6, 3, 2}; 

std::array在棧上分配內存,或在結構直接,就像一個固定的數組。你可以通過比較尺寸來測試。

如果你需要一個共同的基類,你可以這樣做:

struct C { 
    virtual ~C() {} 
    virtual int* data(); 
    virtual std::size_t size(); 
}; 

然後overriting論文在A

template<std::size_t size> 
struct A : C { 
    A(std::array<int, size> _values) : values{_values} {} 

    int* data() override { 
     return values.data(); 
    } 

    std::size_t size() override { 
     return size; 
    } 

private: 
    std::array<int, size> values; 
}; 
+1

不是downvoter,但要小心你稱之爲堆棧。 'new B()'不會將'values'放在堆棧上。 – user4581301

+0

我稱之爲堆棧的是本地堆棧,因爲聲明「B」的大小受數組大小的影響。 –

+0

有一點需要注意的是,子類不會與其他使用不同大小的子類共享一個基類。 –