2014-01-12 42 views
0

如何訪問派生類中的基類數據成員? 我想使用docElem數據成員已初始化customizeCSMWindow()構造函數在subMenuLists::changeWidget()如何訪問基類的公共數據成員?

class myWidget 
{ 
public : 
    QDomElement docElem; 
    QDomDocument *menuOrderXMLFile; 
}; 

class subMenuLists : public QListWidget , public myWidget 
{ 
     Q_OBJECT 
public slots: 
     void changeWidget(int index); 
}; 

class customizeCSMwindow : public QDialog , public myWidget 
{ 
    Q_OBJECT 
public : 
    subMenuLists *menuList; 
    customizeCSMwindow(QString);  

} 

customizeCSMwindow::customizeCSMwindow(QString fileName) 
{ 
menuOrderXMLFile = new QDomDocument(); 
file = new QFile(fileName); 
QString errorStr; 
int errorLine; 
int errorColumn; 
if(!menuOrderXMLFile->setContent(file, false , &errorStr, &errorLine, 
          &errorColumn)) 
    std::cout<<"not found \n"; 
else 
     docElem = menuOrderXMLFile->documentElement(); 
} 

void subMenuLists::changeWidget(int index) 
{ 
    clear(); 
// How to access that docElem here?? 
} 

如何訪問void subMenuLists::changeWidget()功能docElem

編輯

我想解釋一下我的問題,看你能不能幫我。我想要的是,得到docElem這是cusomizeCSMWidnow construtor分配的值,在subMenuList::changeWidget()函數中。截至目前,當我訪問changeWidget函數中的docElem時,它會給出空值/未初始化的值。

+0

什麼是'Q_OBJECT'?順便說一句 - 擁有公共數據成員不是一個好主意。最好有getter和setter –

+3

只需使用它:'docElem.doWhatever();'? –

+0

允許訪問docElem,但事情是我沒有得到在customCSMWindow的構造函數中分配給它的docElem的值。我錯過了什麼嗎? – user3187568

回答

1

customizeCSMwindow類似於subMenuLists類型元素的容器。容器和元素每個都有成員docElem。您嘗試訪問容器customizeCSMwindowsubMenuLists成員docElem

這不能直接工作。要麼給容器的元素指向容器的指針,要麼在subMenuLists::changeWidget的調用中指向容器的指針。

舉例說明上述元素的指針容器:

#include <string> 
#include <iostream> 

class myWidget 
{ 
public : 
    std::string docElem; 
}; 

class customizeCSMwindow; 

class subMenuLists : public myWidget 
{ 
    customizeCSMwindow* m_pContainer; // Pointer to the container 
public: 
    subMenuLists(customizeCSMwindow* pContainer) : 
     m_pContainer(pContainer) 
    {} 
    void changeWidget(int index); 
}; 

class customizeCSMwindow : public myWidget 
{ 
public: 
    subMenuLists *menuList; // This pointer makes customizeCSMwindow to a container. 
    customizeCSMwindow(); 
    void setMenuList(subMenuLists* ml) { 
     menuList = ml; 
    } 
}; 

customizeCSMwindow::customizeCSMwindow() // Here we set docElem of the **container**. 
{ 
    docElem = " docElem in customizeCSMwindow"; 
} 

void subMenuLists::changeWidget(int index) // In the **element** we want to access the docElem of the **container** 
{ 
    // How to access that docElem here?? 
    std::cout << "\nIn changeWidget:" << m_pContainer->docElem << "\n"; 
} 

int main() { 
    customizeCSMwindow job; 
    subMenuLists menu(&job); 

    job.setMenuList(&menu); 

    menu.changeWidget(0); 
} 

在評論你問:「還有一兩件事,做這樣的設計好看或者你可以提出任何更好的辦法?有兩個不同的類可以訪問相同的變量,即docElem?「

這很大程度上取決於目標。如果在menuList中可能有多個元素,則應避免使用原始指針。您應該使用std::shared_ptrstd::vector。如果這只是某種類型的指針實現pimpl(請參閱Scott Meyers有效的C++),那麼原始指針可以很好。

關於良好的實現有太多要說的。您需要閱讀關於該書的書籍(例如,標準書籍[Stroustrup:C++]或[Scott Meyers:Effective C++],或者您可以通過Google在討論中輕鬆找到的很好的參考書籍)。

menuList中的多個元素只有一個可能的實現。

#include <string> 
#include <iostream> 
#include <stdexcept> // for std::out_of_range 
#include <memory> // for std::shared_ptr 
#include <vector> 

class myWidget 
{ 
public : 
    std::string docElem; 
}; 

class customizeCSMwindow; 

class subMenuLists : public myWidget 
{ 
    customizeCSMwindow* m_pContainer; // Pointer to the container 

    /* The private constructor only allows the friend customizeCSMwindow to 
     construct elements of subMenuLists. This makes sure that pContainer is right. */ 
    subMenuLists(customizeCSMwindow* pContainer) : 
     m_pContainer(pContainer) 
    {} 
public: 
    void changeWidget(int index); 

    friend customizeCSMwindow; 
}; 

class customizeCSMwindow : public myWidget 
{ 
    /* shared_ptr takes care of the deletion of allocated memory for subMenuLists. */ 
    typedef std::shared_ptr<subMenuLists> pSubMenuLists_t; 

    /* Automatically runs the destructors of the elements when menuList is destructed. */ 
    std::vector<pSubMenuLists_t> menuList; // This pointer makes customizeCSMwindow to a container. 
public: 
    customizeCSMwindow(); 

    /* The only and right way to generate new MenuLists. Takes care of the right m_pContainer. */ 
    void addMenuLists(/*Stuff needed for the construction of an element of type subMenuLists*/) { 
     pSubMenuLists_t ml(new subMenuLists(this /* stuff for subMenuLists */)); 
     menuList.push_back(ml); 
    } 

    /* One possible interface to make iteration over menuList possible. (There are other ways too.) */ 
    size_t sizeMenuList() { 
     return menuList.size(); 
    } 
    subMenuLists* getMenuListItem(size_t i) throw(std::out_of_range) 
    { 
     return menuList.at(i).get(); 
    } 
}; 

customizeCSMwindow::customizeCSMwindow() // Here we set docElem of the **container**. 
{ 
    docElem = " docElem in customizeCSMwindow"; 
}  
void subMenuLists::changeWidget(int index) // In the **element** we want to access the docElem of the **container** 
{ 
    // How to access that docElem here?? 
    std::cout << "\nIn changeWidget:" << m_pContainer->docElem << "\n"; 
} 

int main() { 
    size_t i; 
    customizeCSMwindow job; 

    job.addMenuLists(); 

    for(i=0; i!=job.sizeMenuList(); i++) 
     job.getMenuListItem(i)->changeWidget(0); 

    return 0; 
} 

/* 
    Local Variables: 
    compile-command: "g++ -std=c++11 test3.cc -o a.exe; ./a.exe" 
    End: 
*/ 
+0

謝謝@Tobias,我明白了。 還有一件事,這個設計看起來不錯嗎?或者你能否建議任何更好的方法來使用相同的變量,即docElem可以在兩個不同的類中訪問? – user3187568

+0

我是C++/OOP編程的新手,所以我想知道這個'容器'是否標準? ps:我喜歡這個方法btw :) – user3187568

+1

我編輯了答案。答案中的第一個例子以最簡單的方式顯示了問題。第二個例子顯示了一個可能的實施方案,其中包含一些保護措施。但是,正如答案中所述。實施是否具有優勢或劣勢也很大程度上取決於目標。 – Tobias

1

派生類可以訪問父級的公共和受保護成員。 您只需使用docElem就好像它是subMenuLists的成員一樣。

+0

允許訪問docElem,但事情是我沒有得到在customCSMWindow的構造函數中分配給它的docElem的值。 我錯過了什麼嗎? – user3187568

0

繼承的主要目的是使基類中的公共(和受保護的)數據和函數可用於派生類,就好像數據和函數是在派生類本身中聲明的一樣。

例如:

class BASE { 
public: 
    int baseData; //the data you want to use 
    void workOnBaseData(){ 
     baseData = 5; 
    } 
}; 

class DERIVED : public BASE { 
public: 
    int someData; //data member of the derived class 
    void workOnBaseAndSomeData(){ 
     someData = baseData; //baseData is already known to DERIVED via inheritance 
    } 
}; 

執行該代碼後一個發現someData = 5! 希望這有助於。

相關問題