Abstract class question?

Dec 29, 2020 at 12:14am
I want to try practice a few things that I have learned by making a very small simple console based game. I was going to make 3 characters, player, enemy and enemy boss, and was going to have them inherit from entity. So I thought I should have entity be an abstract class, but is it normal for an abstract class to have all of its functions and variables virtual? This would be about 7 or 8 functions, and 3 or 4 member variables? From what I have found, most abstract classes only have 1 or so functions virtual, but I do not know if this is just because it is tutorial code I am looking at and therefore it is being kept simple.

EDIT : I have just read that virtual member variables are not a thing, so it would just be virtual member functions then in the abstract class. Not sure how I would handle the private variables
Last edited on Dec 29, 2020 at 12:23am
Dec 29, 2020 at 2:43am
is it normal for an abstract class to have all of its functions [...] virtual?
Yes, there's nothing unusual about such a design. Furthermore, a class without any data members that only contains pure virtual member functions is called an "interface".

Not sure how I would handle the private variables
Since the class doesn't contain any code, there would be no way to access private members if you were to declare any. There's nothing wrong with declaring such members, although it would be a bit strange. In classes intended to be inherited from, it's much more common for non-public members to be declared protected, rather than private.
Last edited on Dec 29, 2020 at 2:43am
Dec 29, 2020 at 3:04am
> but is it normal for an abstract class to have all of its functions and variables virtual?

Normal for all except the (defaulted) constructors and assignment operators.


> Not sure how I would handle the private / protected members

A base class virtual function need not be accessible (it can be declared private or protected) for it to be overridden in a derived class.


Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <string>

#define TEST_ENTITY

struct entity
{
    // defaulted constructors are not virtual; they can't be virtual
    // defaulted assignment operators are usually not virtual 
    // rule of five defaults: "When a base class is intended for polymorphic use,
    // its destructor may have to be declared public and virtual.
    // This blocks implicit moves (and deprecates implicit copies),
    // and so the special member functions have to be declared as defaulted"
    // see: https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_zero
    entity() = default ;
    entity( const entity& ) = default ;
    entity( entity&& ) noexcept = default ;
    entity& operator= ( const entity& ) = default ;
    entity& operator= ( entity&& ) noexcept = default ;

    virtual ~entity() = default ; // defaulted virtual destructor

    // all other functions are pure virtual

    virtual std::string name() const = 0 ;
    virtual void name( std::string ) = 0 ;

    // note that a virtual function can be private
    // and it can still be overridden in a derived class
    private: virtual void helper() = 0 ;

    // just for testing helper: a public function to call the private virtual function helper()
    #ifdef TEST_ENTITY
        public: void call_helper()
        {
            std::cout << "calling helper() on object with name '" << name() << "' -> " ;
            helper() ;
        }
    #endif // TEST_ENTITY
};

int main()
{
    struct player : entity
    {
        explicit player( std::string name ) : _name( std::move(name) ) {}

        std::string _name ;
        virtual std::string name() const override { return _name ; }
        virtual void name( std::string new_name ) override { _name = std::move(new_name) ; }

        private: virtual void helper() override { std::cout << "overridden main::entity::helper()\n" ; }
    };

    player p { "a_player" } ;
    entity& e = p ;
    e.call_helper() ;
}


http://coliru.stacked-crooked.com/a/d849342aeacfc277
Topic archived. No new replies allowed.