вызов правильной формы полиморфной функции. C ++ - PullRequest
0 голосов
/ 14 сентября 2011

У меня проблемы с поиском способа вызвать правильную форму полиморфной функции без редактирования функции int main ().

void Print(Operator*  someOp); //function definition

int main(int argc, char* const argv[])
{
Operator* ptr = NULL;

...
... //this is the body


void Print(Operator*  someOp)
 // Writes description of card to stdout
 {
    someOp->WriteOperator();         // Hint:  Polymorphic function
 }

}

Я держал основную функцию как можно более краткой, как указано выше, но вся функция находится внизу для любых ссылок.

хорошо, значит, есть класс операторов, который имеет функцию с именем void WriteOutput () но затем UnaryOp наследуется от Operator, а также имеет другую пустую функцию WriteOutput ()

но они выводят разные данные. поэтому мой вопрос заключается в том, как я могу сделать основной вызов правильной функции. Я знаю, что если бы я мог редактировать main, я мог бы просто установить someOp для любого класса, который я хотел бы вызвать, но я не могу редактировать main. единственные файлы, которые я могу редактировать, это operator.h и UnaryOp.cpp в программе есть больше файлов, но у них всех одна и та же проблема вызова функций, поэтому, если я смогу это исправить, остальное будет легко.

// main.cpp
//
// Driver program for Card program which is used to test each
// class member function.
//
// DO NOT MODIFY OR SUBMIT THIS FILE
//

// List of allowed include files appear below
#include <iostream>
#include <fstream>
#include <string>
#include "operator.h"
#include "unaryop.h"
#include "binaryop.h"
#include "factorial.h"
#include "plus.h"
#include "minus.h"
#include "times.h"
#include "slash.h"


using namespace std;                     // Global using declaration

void Bar();                              // Prototype for Bar function
void Print(Operator*  someOp);           // Prototype for Print function



// Start of main() function


int main (int argc, char* const argv[])  // Command-line arguments (more on this later)
{
ifstream inputs;       // Input file stream variable    for test file
char op, ch;     // Hold operation and optional char input from test file
string   comment;                      // Holds comment string input from test file
Operator* ptr = NULL;                  // Pointer to abstract operator object
int      operand1,operand2;            // Holds operand values input from test file


 // Output usage message if test input file name is not provided
 if (argc != 2)
  {
   cout << "Usage:\n  project02  <inputfile>\n";
    return 1;
  }

  // Attempt to open test input file -- terminate if file does not open
  inputs.open(argv[1]);
  if (!inputs)
  {
    cout << "Error - unable to open input file" << endl;
    return 1;
  }

  Bar();

  // Process comment line from input file
  getline(inputs, comment);                          // Input file header comment
  cout << endl << comment << endl << endl;           // Output file header comment


  // Below is the primary loop that processes each operation appearing within the test   file.
  // Starts with an initial priming read of first operation

  inputs >> op;                                      // Attempt to input     first test operation from file

  while (inputs)                                     // While Not-EOF
  {
    switch (op)                                      // Process operation input from test file
    {
     case '#':   // Test file comment
            getline(inputs, comment);      // Input and echo the comment appearing in the    test file
            cout << '#' << comment << endl;
            break;

     case 'p':   // Print Operator 
            Print(ptr);
            break;  

     case '~':   // Print Bar
            Bar();                         // Function definition appears at the end of     this file
            break;              

     case 'o':   // Set output to desired value
                 inputs >> operand1;
                 ptr->SetOutput(operand1);
                 break;

     case 's':   // Set symbol to desired value
                 inputs >> ch;
                 ptr->SetSymbol(ch);
                 break;

     case ';':   // Reset operand one and trigger output update
                 inputs >> operand1;
                 {
                   UnaryOp* temp = (UnaryOp*) ptr;    // Treat as a unary operator pointer
                   temp->SetOperand(operand1);
                 }
                 break;

     case ':':   // Reset both operands and trigger output update
                 inputs >> operand1 >> operand2;
                 {
                   BinaryOp* temp = (BinaryOp*) ptr;  // Treat as a binary operator pointer
                   temp->SetOperand1(operand1);       
                   temp->SetOperand2(operand2);
                 }
                 break;

     case 'c':   // Use symbol input from file to invoke appropriate constructor
                 inputs >> op;              // Input symbol
                 try
                 {
                   cout << "Constructor -- ";
                   switch (op)
                   {
                     case '?':  // Operator
                                ptr = new Operator;
                                break;
                     case 'u':  // UnaryOp
                                inputs >> operand1;
                                ptr = new UnaryOp(operand1);
                                break;
                     case '!':  // Factorial
                                inputs >> operand1;
                                ptr = new Factorial(operand1);
                                break;
                     case 'b':  // BinaryOp
                                inputs >> operand1 >> operand2;
                                ptr = new BinaryOp(operand1, operand2);
                                break;
                     case '+':  // Plus
                                inputs >> operand1 >> operand2;
                                ptr = new Plus(operand1, operand2);
                                break;
                     case '-':  // Minus
                                inputs >> operand1 >> operand2;
                                ptr = new Minus(operand1, operand2);
                                break;
                     case '*':  // Times
                                inputs >> operand1 >> operand2;
                                ptr = new Times(operand1, operand2);
                                break;
                     case '/':  // Slash
                                inputs >> operand1 >> operand2;
                                ptr = new Slash(operand1, operand2);
                                break;
                     default:   cout << "Error: unrecognized object" << endl;
                    } // End switch (op)


                    cout << "Successful"; 
                  }  // End try
                  catch ( ... )                // Catch any exception thrown above
                  { 
                    cout << "Failed";  
                  }

                  cout << endl;                  
                      break;

      case 'd':   // Destructor
                  try
                  {
                    cout << "Destructor -- ";
                    delete ptr;                        // Deallocate card 
                   cout << "Successful";
                   ptr = NULL;                        // Make sure that ptr is not a dangling pointer
              }
              catch ( ... )
              {
                cout << "Failed";
              }
              cout << endl;
              break;        

  default:    // Error
              cout << "Error - unrecognized operation '" << op << "'" << endl;
              cout << "Terminating now..." << endl;
                  return 1;
              break;
}

inputs >> op;                                    // Attempt to input next command
  }

  cout << endl;

  return 0;
}

/************** Implementation of Print() and Bar() functions ********************/

// DO NOT MODIFY THIS CODE

void Bar()
// Bar() -- prints horizontal bar
    {
    cout << "#################################################################" << endl;
    }  // End Bar()


void Print(Operator*  someOp)
// Writes description of card to stdout
{
    someOp->WriteOperator();         // Hint:  Polymorphic function
}

/**************  End of main.cpp  ***************/

1 Ответ

0 голосов
/ 14 сентября 2011

Красота полиморфизма в C ++ состоит в том, что он всегда вызывает правильный метод.Вы, вероятно, забыли сделать WriteOperator() virtual.Это синтаксис для переопределения поведения родителя.Таким образом, вы можете сохранить указатель типа базового класса, указать его на любой дочерний объект и вызвать правильный метод без приведения (A UnaryOp в конце концов Operator).Это работает при условии, что реальным типом базового объекта является дочерний.

Внутри вашего файла Operator.cpp он может выглядеть примерно так:

void Operator::WriteOperator() 
{
    ...
}

И в заголовке:

virtual void WriteOperator();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...