2014-03-07 73 views
0

我的場景在以下示例中被簡化了:無障礙C++向量的從基類

#include <iostream> 
#include <vector> 
using namespace std; 
class C; 
class A 
{ 
    protected: 
    C * cPointer; 
    A(); 
    virtual void updateList() = 0; 
    void callFunc(); 
}; 

class B : public A 
{ 
    private: 
    vector<int> list; 
    void updateList(); 
    public: 
    void callFromA(); 
}; 

class C 
{ 
    friend class A; 
    friend class B; // I want to get rid off this declaration 
    private: 
    int sum; 
    void set_sum(int val); 
    public: 
    static C * getCPointer(); 
}; 

A::A() 
{ 
    cPointer = C::getCPointer(); 
} 

void A::callFunc() 
{ 
    updateList(); 
} 

void B::updateList() 
{ 
    list.push_back(2); 
    list.push_back(4); 
    int s = 0; 
    for(unsigned int i=0; i<list.size(); i++) 
    { 
    s += list[i]; 
    } 
    cPointer->set_sum(s); 
} 

void B::callFromA() 
{ 
    callFunc(); 
} 

void C::set_sum(int val) 
{ 
    sum = val; 
    cout << "Sum at C is: " << sum << endl; 
} 

C * C::getCPointer() 
{ 
    static C cPointer; 
    return & cPointer; 
} 

int main(int argc, char ** argv) 
{ 
    B b; 
    b.callFromA(); 
    return 0; 
} 

此示例工作正常。但是我想擺脫C類中的「朋友類B」聲明並實現類似的功能。其實我想有以下任一操作:

  1. 的C)從B :: updateList()無障礙:: set_sum(無類C.

    的「朋友B類」的聲明,這將是不可能的
  2. A :: callFunc()中的B :: list的可訪問性,我可以將B :: updateList中的邏輯推送到A :: callFunc(),這基本上意味着能夠從基類訪問派生類中的列表類。通過這種方式,我將能夠訪問A :: callFunc()的set_sum()由於C類

任何想法,「朋友A級」的聲明來實現這個不涉及重大設計變更是可取的!

謝謝!

+0

你是從'B :: callFromA()'調用全局函數'callFunc()'嗎?它在哪裏? –

+1

這裏的問題可能是你將有許多基類'A'的派生類,並且你不想列出所有這些類作爲'C'的朋友。爲了解決這個問題,你可以只讓基類'A'成爲'C'的朋友,並且你可以將一個受保護的'set_sum()'方法放入'A'中,所有派生類都可以調用'A' :: set_sum'確實將呼叫轉發到'C :: set_sum'。這個轉發函數調用將被編譯器優化掉。 – pasztorpisti

+0

@barakmanos:callFunc()在A中作用域,並從B :: callFromA()中調用,因爲B是從A派生而來的。 –

回答

0

我不確定我是否理解您的所有限制,但也許這對您更好。基本上,您可以使用虛擬功能從A訪問B::list。我已經評論了代碼中的更改。

#include <iostream> 
#include <vector> 
using namespace std; 
class A; 

class C 
{ 
    friend class A; 
private: 
    int sum; 
    void set_sum(int val); 
public: 
    static C * getCPointer(); 
}; 

class A 
{ 
protected: 
    C * cPointer; 
    A(); 
    virtual int getS() = 0;    // virtual function to calculate data from vector in derived class B 
    virtual void updateList() 
    { 
     cPointer->set_sum(getS());  // A is friend of C, so you can access B data from A 
    } 
    void callFunc(); 
}; 

class B : public A 
{ 
private: 
    vector<int> list; 
    void updateList(); 

    int getS()       // concrete implementation to access vector data 
    { 
     int s = 0; 
     for (unsigned int i = 0; i < list.size(); i++) 
     { 
      s += list[i]; 
     } 
     return s; 
    } 


public: 
    void callFromA(); 
}; 

A::A() 
{ 
    cPointer = C::getCPointer(); 
} 

void A::callFunc() 
{ 
    updateList(); 
} 

void B::updateList() 
{ 
    list.push_back(2); 
    list.push_back(4); 
    A::updateList();     // Call to super implementation 
} 

void B::callFromA() 
{ 
    callFunc(); 
} 

void C::set_sum(int val) 
{ 
    sum = val; 
    cout << "Sum at C is: " << sum << endl; 
} 

C * C::getCPointer() 
{ 
    static C cPointer; 
    return &cPointer; 
} 

int main(int argc, char ** argv) 
{ 
    B b; 
    b.callFromA(); 
    return 0; 
} 
+0

感謝您的評論..我不允許將它作爲公共職能,因爲這是一個內部功能,不應該暴露給用戶的.​​.但是,我們只能在受保護/私人範圍內添加一些新的東西! –

0

您無法在基類period中訪問派生類的成員。手頭的對象可能是基類,甚至是完全不相關的派生類,並且保證了「有趣」的連續性。任何要求這樣做的設計都被嚴重破壞,需要重新思考。

你可以讓想要這樣做的基類的成員函數變成虛擬的,並且在派生類中重新定義它來做任何你想到的變態。同時,如果被調用,基類的貞潔成員可以拒絕,以合理的方式表示錯誤。這樣你就可以保證沒有任何不愉快的事情會發生。