-2

I have two classes A and B that derive from an abstract class, Letter. At runtime, I would like to call a function that differs between the derived classes depending on the user input. The following code performs the functionality I want:

Letter.h:

#pragma once
#include <iostream>

class Letter
{
public:
    virtual void PrintAlphabetPosition() = 0;
    virtual ~Letter(){};
};

A.h:

#include "Letter.h"

class A : public Letter
{
public:
    virtual void PrintAlphabetPosition() { std::cout << "1" << std::endl; };
    virtual ~A(){};
};

B.h:

#include "Letter.h"

class B : public Letter
{
public:
    virtual void PrintAlphabetPosition() { std::cout << "2" << std::endl; };
    virtual ~B(){};
};

main.cpp:

#include <iostream>
#include "Letter.h"
#include "A.h"
#include "B.h"

void main() {
    Letter* letter;
    char input;
    std::cin >> input;
    if (input == 'A') {
        letter = new A();
    } else {
        // Default to B
        letter = new B();
    }
    letter->PrintAlphabetPosition(); // Prints 1 or 2 as expected

    delete letter;
}

My question is, is there a way I can perform the functionality in main.cpp without instantiating A or B (not even a singleton)? Every single function I will have in these two classes will never depend on the particular instance of the class.

I considered turning A and B into 'static' classes by declaring all member functions and variables as static, and then hiding the constructor as private, similar to the answer to this question: How do you create a static class in C++?. However, the static declaration would conflict with the virtual declaration.

I also tried turning A and B into abstract classes by declaring PrintAlphabetPosition() as pure virtual functions too and moving the implementation into their respective .cpp files. However, how would I then be able to dynamically choose between A::PrintAlphabetPosition() and B::PrintAlphabetPosition() at runtime?

EDIT: I should mention for clarity that classes A and B act as utility classes that implement Letter differently, and they have many more functions. Furthermore, there are much more derived classes of Letter that I wish to use (not just A and B).

xyhu617
  • 26
  • 5
  • 1
    No that's not possible. Why do you need that? – user0042 Oct 26 '17 at 04:24
  • 2
    What is the *actual* problem you try to solve? *Why* do you want to do that? And how do you think it would ever work? This seems like [an XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). (Oh and *is* possible to do it, with some trickery, but that will lead to [*undefined behavior*](http://en.cppreference.com/w/cpp/language/ub) and quite possibly crashes) – Some programmer dude Oct 26 '17 at 04:25
  • If you think about the guts of how the compiler has to set all this up, it's theoretically possible to call `A::PrintAlphabetPosition` or `B::PrintAlphabetPosition` without an instance, because the functions don't refer to any instance variables. But it shouldn't be surprising that the mechanism for making those calls would invoke UB. There may be a way to do what you want, but I expect you'll have to further explain your actual problem. You seem to want a sort of hybrid between `virtual` and `static`, but `virtual` inherently requires an instance. – Dave M. Oct 26 '17 at 04:30
  • What i am wondering is for the virtual mechanism to work, one has to assign an instance to `letter`.On what lines could there be a workaround? – Gaurav Sehgal Oct 26 '17 at 04:34
  • Are you looking for [`std::function`](http://en.cppreference.com/w/cpp/utility/functional/function) to hold a simple delegate? – user0042 Oct 26 '17 at 04:37
  • 1
    If you don't create an instance then how would it know whether it should print 1 or 2? – user253751 Oct 26 '17 at 04:37
  • As to why I need to do this: classes A and B act as utility classes, and so it did not feel right to me to instantiate from an OOP perspective. – xyhu617 Oct 26 '17 at 04:38
  • 1
    You do know that in C++ you can have free functions that are not member of any class, right? – Bo Persson Oct 26 '17 at 05:08
  • As commented already, this questions smells of an **XY Problem**. The code you show can be implemented without any classes at all. – Drew Dormann Oct 26 '17 at 05:24
  • 1
    "Utility classes" are in most cases not really needed as *classes*. Instead I suggest a redesign where the utility functions are put inside a namespace, and takes the objects they need to work on (if any) as arguments. – Some programmer dude Oct 26 '17 at 06:55
  • 1
    I repeat - If you don't create an instance then how would it know whether it should print 1 or 2? – user253751 Oct 26 '17 at 22:08

2 Answers2

1

What you're looking for isn't possible with virtual functions, because these need an instance inherently.

What you can do though is to have a std::function variable, that is initialized from either class As or Bs `static function:

class A {
public:
     static void PrintAlphabetPosition();
};

class B {
public:
     static void PrintAlphabetPosition();
};

void main() {
    std::function<void()> letterFn;
    char input;
    std::cin >> input;
    if (input == 'A') {
        letterFn = A::PrintAlphabetPosition;
    } else {
        // Default to B
        letterFn = B::PrintAlphabetPosition;
    }
    letterFn(); // Prints 1 or 2 as expected
}
user0042
  • 7,917
  • 3
  • 24
  • 39
  • 1
    Note that pointer function can replace `std::function` in current case: `void (*letterFn)()`. but `std::function` syntax is easier. – Jarod42 Oct 26 '17 at 10:07
0

If the function doesn't need to refer to a particular object (which must be true if you want to be able to call it without instantiating anything), you should be able to rewrite it as a static method. You could then call A::PrintAlphabetPosition() or B::PrintAlphabetPosition() to call the one you want.

If you also want a virtual method, you could add this as well and have it call the class-specific static method. I think you'll need to use different names for the virtual and static methods.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • if i am not wrong you are suggesting to have virtual functions call the actual static methods, but then again virtual functions would be needing an instance.No? – Gaurav Sehgal Oct 26 '17 at 04:52
  • You call the static functions when you don't want an instance, you call the virtual functions when you already have an instance and you want it to find the method based on the instance. – Barmar Oct 26 '17 at 04:53
  • So in case i don't have an instance, i'll have to manually check which static method to call since i cannot utilize this functionality provided by virtual functions. – Gaurav Sehgal Oct 26 '17 at 04:56
  • Of course. If there's no instance, how could it know which class's method to call unless you tell it explicitly in some way? – Barmar Oct 26 '17 at 05:02
  • 1
    @GauravSehgal If you don't want a big `if/else` block with all the cases, you could use a `std::map` that maps letters to functions. – Barmar Oct 26 '17 at 05:05