Home > Blockchain >  Is it safe to cast a class to a derived class that just adds additional functions?
Is it safe to cast a class to a derived class that just adds additional functions?

Time:10-30

I have a class that contains a lot a data. Depending on the situation I need to output this data in different ways. I want the output routines for each of those situations separated and I want to keep the base class clean of that.

Is it absolutely safe to cast to a derived class that does NOT add any data members but just non-virtual functions?

#include <stdio.h>

class Base {
public:
  Base() { printf("Base()\n"); }
  
  double A = 3.14;
  int B = 5;
  int C = 42;
};

class Derived1 : public Base {
public:
  Derived1() { printf("Derived1()\n"); }
  
  void DoStuff() {
    // doing stuff with base class's data
    printf("  A = %.4f\n", A);
    printf("  B = %d\n", B);
    printf("  C = %d\n", C);
  }
};

class Derived2 : public Base {
public:
  Derived2() { printf("Derived2()\n"); }

  void DoStuff() {
    // doing stuff with base class's data in a slightly different way
    printf("  A = %.4f, B = %d, C = %d\n", A, B, C);
  }
};

class OtherBase {
public:
  OtherBase() { printf("OtherBase()\n"); }
  int D = 10;
};

class Derived3 : virtual public OtherBase, virtual public Base {
public:
  Derived3() { printf("Derived3()\n"); }
  
  void SomeFunction() {
    A = 6.28;
    B = 1;
    C = 500;
    printf("Done some other stuff.\n");
  }
};

int main() {
  printf("Base class\n\n");
  Base* Instance = new Base();
  printf("Cast to Derived1:\n");
  static_cast<Derived1*>(Instance)->DoStuff();
  printf("Cast to Derived2:\n");
  static_cast<Derived2*>(Instance)->DoStuff();
  
  printf("\nOther class derived from base class\n\n");
  Derived3* Instance2 = new Derived3();
  Instance2->SomeFunction();
  printf("Cast to Derived1:\n");
  static_cast<Derived1*>(static_cast<Base*>(Instance2))->DoStuff();
  printf("Cast to Derived2:\n");
  static_cast<Derived2*>(static_cast<Base*>(Instance2))->DoStuff();
  printf("c-style cast to Derived1:\n");
  ((Derived1*) Instance2)->DoStuff();
  printf("c-style cast to Derived2:\n");
  ((Derived2*) Instance2)->DoStuff();
  return 0;  
}

The part where class "Derived3" (that has virtual inheritance of "Base") is cast to "Base" first and then to "Derived1"/"Derived2" does not look very good to me but I know how c-style casts are frowned upon in the c community. In this small example however, the c-style cast are compiling and working nicely:

I know there is the issue with multiple inheritance where a cast to one of the base classes can have a different pointer address then the inherited class it was cast from. So I understand that it might be too dangerous to rely on it.

Are the static casts I did in the example at the top safe?

CodePudding user response:

No, this isn't safe. The behaviour of the program is undefined.

Static casting to a derived type is safe only when the dynamic type of the object is that derived type (or a further derived type).

  • Related