调用多态函数的正确形式.c++

calling the correct form of a polymorphic function. c++

本文关键字:c++ 多态 函数 调用      更新时间:2023-10-16

我有问题,找到一种方法来调用多态函数的正确形式,而不编辑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调用成为正确的函数。我知道,如果我能编辑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  ***************/

c++中多态性的美妙之处在于它总是调用正确的方法。你可能忽略了把WriteOperator()变成virtual。这就是覆盖父元素行为的语法。通过这种方式,您可以保留基类类型的指针,将其指向任何子对象,并调用正确的方法而无需强制转换(毕竟,UnaryOp Operator)。如果底层对象的实际类型是子对象的类型,则此操作有效。

在Operator.cpp文件中,可能看起来像这样:

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

在header中:

virtual void WriteOperator();