Are subclasses that only change the members valid practice?

122 Views Asked by At

Lets say I have a class A that has a member of type int. I have a class B which is a subclass of A. B is meant to initialize the members to some state and has no other purpose.

#include <string>
#include <iostream>
struct A {
    int someInt;
    A() : someInt(33){}
};

struct B : public A {
    B() {
        someInt = 4;
    }
};
int main() {

    A a = A();
    A b = B();
    std::cout<< a.someInt << std::endl;
    std::cout << b.someInt << std::endl;
}

Notice how I use A b = B() where object slicing should occur. However since B doesn't add anything to A, is it a valid alternative to using A with different constructor parameters (or any other form of creating instances of A)?

Edit: The background is that I have a class that has some complex setup. Putting the initialization into separate child class is way easier than lets say write a constructor, factory or builder.

3

There are 3 best solutions below

4
On BEST ANSWER

To answer your question as directly as possible, what you're doing is certainly "valid" in the sense that it will compile and run and produce a correct result. It's probably not the most common way to accomplish this though.

My recommendation for a more idiomatic approach would be to use a common base class and templatize all of your derived versions. Basically make the compiler do the work of setting the integer value you want.

struct ABase {
    int someInt;
    ABase() = delete;
    ABase(int initVal) : someInt(initVal) { }
};

template<int T>
struct A : public ABase {
    A() : ABase(T) {}
};

int main() {
    ABase a = A<33>();
    ABase b = A<4>();
    std::cout << a.someInt << std::endl;
    std::cout << b.someInt << std::endl;
}

This is probably less code overall (especially if you have more than just two versions of this class), and much more flexible.

0
On

More common and less error prone method is to define static methods to create your class instances:

struct A {
    static A makeA();
    static A makeB();
};

int main()
{
    auto a = A::makeA();
    auto b = A::makeB();
}

and to prevent even more errors you may want to prohibit creation of instances of A directly, rather than set of static methods by making A ctor private.

3
On

As a better practice,
Use another constructor in class A and this constructor will take parameters OR Use a separate function in class A to do what you want.

And regarding "Putting the initialization into separate child class is way easier than lets say write a constructor, factory or builder" doesn't make sense in this situation, so it's not easier even the code is complex as you said.