0

How would I use the same instance of a class created in main in another class's function?

For example in main I have the code below. A SignatureBlock object is created at the beginning and its toString() function is used shortly after. Later in the code, a Game object is created and its playGame() function is called. My problem is that the playGame() function also needs to use SignatureBlock's toString() function.

It seems to me I only have two choices. Either create a new SignatureBlock object in the Game class and then use the new object's toString() function, or pass the SignatureBlock object created in main to the playGame function.

I don't really like either of these solution and I was wondering if someone had a better way of doing this.

#include <iostream>
#include "Game.h"
#include "SignatureBlock.h"

int main() 
{
    SignatureBlock myBlock;
    bool done = false;
    do
    {
        std::cout << myBlock.toString();

        std::cout <<    "************\n" 
                        "Tic Tac Toe!\n"
                        "************\n";
        std::cout <<    "1. Play game!\n"
                        "2. exit\n"
                        "\nEnter 1 or 2: ";
        std::string option;
        std::getline(std::cin,option);
        if (option == "1")
        {       
            Game myGame;
            myGame.playGame();
        }
        else if (option == "2")
        {
            done = true;
        }
        else
        {
            std::cout << "Invalid input";
        }
    }
    while (!done);

    return 0;
}
Natan Streppel
  • 5,759
  • 6
  • 35
  • 43
navig8tr
  • 1,724
  • 8
  • 31
  • 69
  • 2
    Why don't you like passing the class through? If you pass it as a pointer, then you're not copying data, but it gives your class access to the running instance of SignatureBlock. – Dylan Lawrence Dec 16 '13 at 13:39
  • @DylanLawrence: Objects are *data*, not *code*, so an object cannot "run". – Kerrek SB Dec 16 '13 at 13:41
  • If you don't like passing myBlock, you can pass the return value of myBlock.toString() since this is what you require in playgame() function. – Abhishek Bansal Dec 16 '13 at 13:42
  • you can declare the SignatureBlock global instead of local in your main. Generally, in practice, it's not a good idea - but it may help you in this particular case. Personally I'd pass the instance of the class through a pointer to the function where it's needed – Pandrei Dec 16 '13 at 13:44
  • You could (eugh....) make the instance of SignatureBlock global. – splrs Dec 16 '13 at 13:44

2 Answers2

2

Other options -

  1. Pass a pointer to the toString() method. This is a bit problematic in C++ for several reasons. C++ distinguishes between static and member functions, member function signatures also depend on the class and so on. In addition - invoking a member function (which is what you need) requires a reference to the object. To overcome this you can you use boost's function and boost bind, see example here.

  2. You can declare your SignatureBlock as a global variable so it'll be accessible to any Game object. This is an option, but it's VERY not recommended for various reasons.

I still think passing a pointer or a reference to the SignatureBlock constructor is the best option. If you really want to hide implementation details, have Game expect an "interface" (a pure virtual class) that declares a toString() method and have SignatureBlock inherit from it.

Community
  • 1
  • 1
Vadim
  • 2,847
  • 15
  • 18
  • Yeah I think I'll just go with the pointer. Thanks for the help everyone. – navig8tr Dec 16 '13 at 13:50
  • @navig8tr The only reason to prefer a pointer over a reference is if you want to allow for passing a "null". It doesn't look like you need this functionality, so a reference would be a better option. – juanchopanza Dec 16 '13 at 13:57
  • Okay I'm passing by reference like this: `void playGame(const SignatureBlock &myBlock);` – navig8tr Dec 16 '13 at 14:48
  • @navig8tr - if you pass it as const, make sure toString() is marked as const as well (and that it is indeed a function that does not change the state of the object) – Vadim Dec 16 '13 at 15:04
0

Another way of doing this would be by making toString() a static function. This is good if toString() is used only to run some logic rather than store data in an object and do operations on it. From your use case I believe making toString() static would be the perfect option.

For using static functions you dont need to create any object. Use following line wherever you want to call this function.

SignatureBlock::toString();
Cool_Coder
  • 4,888
  • 16
  • 57
  • 99
  • I thought the same, but usually `toString()` functions are used to write some "instance-specific" data of the object, so making it static would not do the deal, since you don't have access to the object specific data anymore. – Toby Dec 16 '13 at 13:55
  • From the use case and the question it does not appear to me that toString() requires class variables. What it does and how it does can only be answered by OP. – Cool_Coder Dec 16 '13 at 13:57
  • I agree in so far, that the OP just uses `std::cout << myBlock.toString();` without having any specific data in `myBlock`. So yeah, telling from the code he provided it seems it has no object-specific data. – Toby Dec 16 '13 at 14:02
  • The `toString` does use data in the object. – navig8tr Dec 16 '13 at 14:43
  • `toString` combines several string fields (instantiated by a no-arg constructor) and returns them as a single string. – navig8tr Dec 16 '13 at 14:50