How to implement "is also" (extending a method, as used in E language) in C++?

StackOverflow https://stackoverflow.com/questions/22320205

  •  12-06-2023
  •  | 
  •  

Pergunta

In my program I have 3 classes: GeneralHeader, MACHeader and IPHeader. MAC and IP headers are derived from General_Header:

//Headers.h

class GeneralHeader {
public:
    bool Valid;
    void PrintMe();
};

struct MACHeader: public GeneralHeader {
    int DestMAC:48;
    void PrintMe();
};

struct IPHeader: public GeneralHeader {
    int Version;
    void PrintMe();
};

I would like to implement the PrintMe() of GenedralHeader to print all its members and then to extend the PrintMe() method for MACHeader to print also MACHeader's members (so MACHeader.PrintMe() will print both GeneralHeader and MACHeader members). Same for IPHeader - IPHeader.PrintMe() will print GeneralHeader and IPHeader members.

In E language (AOP) it could be easily done by using "is also" to extend the PrintMe() method in MACHeader and IPHeader.

Could you please guide me how to implement it in C++?

Many thanks for any help

Foi útil?

Solução

What you want is to call the PrintMe method of the parent class GeneralHeader from the PrintMe method of IPHeader and MACHeader. This can be done by prefixing the method call with the parent class. Example:

void IPHeader::PrintMe(){
    GeneralHeader::PrintMe(); //Call the super method
    std::cout << "Version: " << Version << std::endl; //Print IPHeader members
}

The method of MACHeader is analoguous.

If you have polymorphism, i.e., you want to call the PrintMe method of a derived class through a pointer or reference of the super class, e.g.:

GeneralHeader* h = new IPHeader();
h->PrintMe();

then you should declare the method in the GeneralHeader class virtual. Otherwise, only PrintMe of GeneralHeader will be called in the above code, even if h is actually an IPHeader. If you use C++11, you might want to declare the methods in the deriving classes override to make sure that they do override GeneralHeader::PrintMe().

Outras dicas

This is done by explicitly calling the base class method first:

void MACHeader::PrintMe() {
  GeneralHeader::PrintMe();
  std::cout << DestMAC;
}

You might also want to consider making the base class' PrintMe method virtual. (The explicit call in the derived class will not trigger dynamic dispatch)

Howeer, if all derivates of GeneralHeader have to print the general header first, consider the template method pattern:

class GeneralHeader {
  virtual void PrintDetails() = 0;
public:
  bool Valid;
  void PrintMe() {
    std::cout << "Validity: " << Valid << '\n';
    PrintDetails();
  }
};

struct MACHeader: public GeneralHeader {
  int DestMAC:48;
  void PrintDetails() {
    std::cout << "Dest: " << DestMAC << '\n';
  }
};

struct IPHeader: public GeneralHeader {
  int Version;
  void PrintDetails() {
    std::cout << "Version: " << Version << '\n';
  }
};

That way every derived class is forced to implement the PrintDetails method, in exchange the ever-returning GeneralHeader::PrintMe(); is not necessary.

That's what virtual methods do. Override the parent method in the derived class and call the parent version before doing your own work.

class GeneralHeader
{
 public:
 virtual void printMe()
 {
  // print all memebers here
 }
};

class IPHeader : public GeneralHeader
{
 public:
 void printMe()
 {
  GeneralHeader::printMe();//to print parent stuff
  //print new stuff here
 }
};

though I don't really know what the is also is for in E language, do you mean something like the following?

GeneralHeader::PrintMe() {
    std::cout<<"valid: "<<Valid<<std::endl;
}

MACHeader::PrintMe() {
    GeneralHeader::PrintMe();
    std::cout<<"dest MAC: ";
    for (int i=0; i<48; ++i)
        std::cout<<i<<":";
    std::cout<<std::endl;
}
IPHeader::PrintMe() {
   GeneralHeader::PrintMe();
   std::cout<<"Version: "<<version<<std::endl;
}

you need to call the function from the mother class GeneralHeader::PrintMe(); in the derived class.

For example you could do this the following way

void MACHeader::PrintMe() 
{ 
   GeneralHeader::PrintMe();
   // ...
} 

Also you could make the inheritance polymorphic declaring the function as virtual. For example

class GeneralHeader {
public:
    bool Valid;
    virtual void PrintMe();
    virtual ~GeneralHeader();
};
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top