如何从基类调用派生类函数?
Posted
技术标签:
【中文标题】如何从基类调用派生类函数?【英文标题】:How to call derived class function from base class? 【发布时间】:2020-01-12 13:38:02 【问题描述】:我是 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()
吗?
【问题讨论】:
malloc
和 realloc
使用不正确。如果你想以你描述的方式使用它,文档应该有一个virtual float getPrice();
(可能应该是const
)。
由于您使用了malloc
和realloc
,您的程序具有未定义的行为。两者的有效用途在 C++ 中非常罕见,我建议您忘记它们的存在。作为初学者,您正确使用它们的可能性很小。始终使用new[]
,或者更确切地说,根本不使用动态分配,而是使用std::vector
和std::string
(以及std::unique_ptr
用于单个对象分配)。您几乎不必使用new
/delete
。
this 会回答您的问题吗?如果您需要更多解释,我可以将其变成完整的答案。
如果要调用Livre
的成员函数,需要创建Livre
类型的对象,而不是其基类Document
。您希望Manager
持有指向Document
和Livre
实例的指针还是只持有后者?如果是前者,如果doc[i]
不 指向Livre
类型的对象,你想发生什么?
【参考方案1】:
您的问题的解决方案
理想情况下,Manager::afficher()
不必知道Document
的详细信息。如果应该将此委托给一个新功能Document::afficher()
,并让每种类型的文档决定要打印哪些信息以及哪些信息可用。这就是多态的原理:
void Manager::afficher()
for (int i = 0; i < count; i++)
doc[i]->afficher();
如果你仍然想侵犯law of demeter,你可以保持你的方法。但是您只能使用可用于所有文档的元素。除非你确定它是 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()
,除非您确定自己在做什么(即,如果您知道何时使用 placement-new 的规则)。
此外,您对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);
为了使其顺利运行,您还应该将 char*
替换为 string
以避免内存管理问题并获得 C++ 字符串的强大功能。
我在解决方案中提到的动态转换与共享指针的工作方式略有不同:您必须使用dynamic_pointer_cast
而不是dynamic_cast
。
最后一句话。每当你在一个类中有一个虚函数时,你也应该将析构函数设为虚函数。
【讨论】:
以上是关于如何从基类调用派生类函数?的主要内容,如果未能解决你的问题,请参考以下文章