2014-01-12 3 views
0

파생 클래스에서 Base 클래스 데이터 멤버에 액세스하려면 어떻게해야합니까? 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에 액세스 할 수?

편집 : 나는, 내 질문에 설명 당신이 나를 도울 수 있는지 확인하고 싶습니다

. 내가 원하는 것은 cusomizeCSMWidnow construtor에 할당되고있는 docElem의 값을 얻으려면 subMenuList::changeWidget() 함수에 있습니다. 지금은 docElemchangeWidget 함수에 액세스 할 때 null/초기화되지 않은 값을 제공합니다.

+0

'Q_OBJECT'란 무엇입니까? BTW - 공개 데이터 멤버가있는 것은 좋지 않습니다. getter와 setter를 가지고 더 좋게 –

+3

그냥 사용하십시오 :'docElem.doWhatever();'?? –

+0

docElem에 대한 액세스가 허용되지만 customCSMWindow의 생성자에서 할당 된 docElem의 값을 가져 오지 못합니다. 내가 놓친 게 있니? – user3187568

답변

1

클래스 customizeCSMwindowsubMenuLists 유형의 요소 컨테이너와 같습니다. 컨테이너와 각 요소에는 각각 docElem이라는 멤버가 있습니다. subMenuListscustomizeCSMwindow 컨테이너 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::vector (std::shared_ptr)을 사용해야합니다. 만약 이것이 포인터 구현 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

고마워요 @ 토비아스, 요점이 있어요. 한 가지 더,이 디자인이 좋아 보이나요? 또는 동일한 변수 (예 : docElem)를 두 개의 다른 클래스에서 액세스 할 수있는 더 좋은 방법을 제안 할 수 있습니까? – user3187568

+0

저는 C++/OOP 프로그래밍의 초보자입니다. 그래서이 '컨테이너'가 표준인지 아닌지 궁금합니다. ps :이 방법을 사용해 주셔서 감사합니다. :) – user3187568

+1

답변을 편집했습니다. 대답의 첫 번째 예는 가장 간단한 방법으로 문제를 보여주었습니다. 두 번째 예제는 몇 가지 가능한 보호 구현 방법을 보여줍니다. 그러나 대답에 명시된 바와 같이. 구현에 장단점이 있는지 여부도 목표에 크게 좌우됩니다. – Tobias

1

파생 클래스는 부모의 공개 및 보호 된 멤버에 액세스 할 수 있습니다. docElemsubMenuLists의 멤버 인 것처럼 사용하십시오.

+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 것을 발견! 도움이 되었기를 바랍니다.

관련 문제