저는 C ++의 초보자이고 아래에서이 코드를 프로그래밍했습니다.
이것은 DOCUMENT.h : 잘 작동하므로 구현 (document.cpp)을 게시하지 않았습니다.
#pragma once
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
class Document {
private:
int id;
char *titre;
public:
Document();
Document(int id, char *titre);
~Document();
Document(const Document &doc);
Document operator+( Document doc);
Document operator=(const Document &doc);
void setId(int id);
int getId();
void setTitre(char *titre);
char *getTitre();
};
class Livre :public Document {
private:
float price;
public:
Livre();
Livre(int id , char *titre,float price);
~Livre();
Livre( Livre &doc);
Livre operator+(Livre doc);
Livre operator=( Livre &doc);
void setPrice(float price);
virtual float getPrice();
};
class Article :public Document {
private:
char *date;
public:
Article();
Article(int id, char *titre , char *date);
~Article();
Article(Article &doc);
Article operator+( Article &doc);
Article operator=( Article &doc);
void setDate(char* date);
char *getDate();
};
MANAGER.H :
#include "Document.h"
class Manager {
private:
Document **doc ;
public:
int count = 0;
Manager();
~Manager();
int ajouter(Document *d);
void afficher();
};
MANAGER.CPP :
#include "stdafx.h"
#include "Manager.h"
Manager::Manager() {}
Manager::~Manager() {}
int Manager::ajouter(Document *d) {
if (count == 0) {
doc = (Document**)malloc( sizeof(Document));
doc[count] = new Document();
doc[0] = d;
}
else {
doc = (Document**)realloc(doc, count * sizeof(Document));
doc[count] = new Document();
doc[count] = d;
}
count++;
return 0;
}
void Manager::afficher() {
for (int i = 0; i < count; i++) {
printf("\nid : %d \n", doc[i]->getId());
printf("titre : %s \n", doc[i]->getTitre());
printf("Price : %f \n", doc[i]->getPrice());
}
}
내 문제는 afficher()
기능 에 있습니다. 나는 getprice()
거기 에서 전화하고 싶지만 getprice()
클래스의 구성원이 아닙니다 Document
: 클래스 의 구성원입니다 Livre
(의 자식 Document
). 전화 할 방법이 getprice()
있습니까?
이상적으로는 Manager::afficher()
의 세부 사항을 알 필요가 없습니다 Document
. 이를 새로운 기능으로 지연시키고 Document::afficher()
각 유형의 문서에서 인쇄 할 정보와 사용 가능한 정보를 결정하도록합니다. 이것이 다형성의 원리입니다.
void Manager::afficher() {
for (int i = 0; i < count; i++) {
doc[i]->afficher();
}
}
그럼에도 불구하고 데메테르 의 법칙 을 위반하고 싶다면 접근 방식을 유지할 수 있습니다. 그러나 모든 문서에 사용할 수있는 요소 만 사용할 수 있습니다. 그것이 Livre라는 것을 확실히 알지 못한다면. 이 경우 동적 캐스팅을 사용할 수 있습니다.
void Manager::afficher() {
for (int i = 0; i < count; i++) {
printf("\nid : %d \n", doc[i]->getId());
printf("titre : %s \n", doc[i]->getTitre());
Livre *l = dynamic_cast<Livre*>(doc[i]); // attempt to see it's a Livre
if (l) { // If it's a Livre l is not null
printf("Price : %f \n", doc[i]->getPrice());
}
else printf ("Price : unknown\n");
}
}
우선 C ++는 C malloc()
가 아니므로 수행하는 작업이 확실하지 않으면 사용해서는 안됩니다 (예 : 새 배치 를 사용할 때 규칙을 알고있는 경우 ).
또한 포인터 포인터를 관리 Manager
하면 재앙으로 직접 연결됩니다. 단일을 할당하면 Document
결국 단일 문서의 배열로 처리 할 수 있지만 캐스팅 마법사를 사용하면 포인터에 대한 포인터가됩니다. 아야!
문서 컬렉션을 관리하는 방법을 변경해야합니다.
doc = (Document**)malloc( sizeof(Document)); //!!!!! NOOO
다른 종류의 특수 문서를 갖는 다형성을 사용하고 싶으므로 클래스를 다음과 같이 만들 수 있습니다.
class Manager {
private:
vector<shared_ptr<Document>> doc ; // safer way
public:
Manager();
~Manager();
int ajouter(shared_ptr<Document> d);
void afficher();
};
shared_ptr<>
포인터처럼 사용되지만 메모리는 스스로 관리합니다. vector
자동 적응 형 : push_back()
요소 만 있으면되고 필요한 경우 자체 크기가 조정됩니다. 그런 다음 배열을 사용하는 것처럼 요소를 인덱싱 할 수 있습니다. 또한 당신을 위해 카운트 vector::size()
;
int Manager::ajouter(shared_ptr<Document> d) {
doc.push_back(d);
}
int Manager::compter() { // you need to add this in your class definition
return doc.size(); // always up-to date count !
}
라이브러리에 새 문서를 추가하는 방법은 무엇입니까?
auto d1 = make_shared<Document>();
...
manager.ajouter(d1);
auto d2 = male_shared<Livre>();
...
manager.ajouter(d2);
이 작업이 원활하게 작동 하려면 메모리 관리 문제를 방지하고 C ++ 문자열의 힘을 얻기 위해 char*
를 string
로 교체해야합니다 .
내 솔루션에서 언급 한 동적 캐스팅은 공유 포인터와 약간 다르게 작동합니다 . dynamic_pointer_cast
대신 dynamic_cast
.
마지막 발언. 클래스에 단일 가상 함수가있을 때마다 소멸자도 가상으로 만들어야합니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다