Suppress output from base class constructor - c++

I have a series of classes that tells the debug stream (std::cout in this case) that it has been created, allowing me to follow the program execution nicely. I have several classes that are subclasses of base classes which are not abstract, which results in a double message when a subclass instance is created. I would like to suppress the output in the base class constructor when it is called from a subclass. I know this probably isn't possible without some fancy trick, if it is even possible at all.
I did think of using the backspace escape sequence \b, and doing just enough of that to delete the previous message not really efficient, but it's debug info, performance isn't that critical then...). I'm not sure of the portability or effectiveness of this approach.
Any ideas are welcome, thanks for the effort!

There's no way to suppress the code in the base constructor, unless the code in the base constructor checks some condition itself. You may achieve this by e.g. passing a special flag to the base constructor (having default value NOT prohibiting the debug output).
class Base
{
public:
Base(bool suppressDebugInfo = false)
{
if (!suppressDebugInfo)
cout << "hallo from base" << endl;
}
};
class Derived : public Base
{
public:
Derived(bool suppressDebugInfo = false) : Base(true)
{
if (!suppressDebugInfo)
cout << "hallo from derived" << endl;
}
};
Outputting \b's won't help if your output is redirected to a file etc.
A decent solution could be to create a virtual function which returns a string, and output the result of that function. This won't however work for your case (calling from constructor), as during the base constructor run the virtual functions behave as if the instance is of the base type, not derived.

This implementation addresses some of Vlad's concerns. The main difference lies in the constructor signature, which is not affected by logging logic, although classes are templates now, which could be frightening, but as you all know, there's no free lunch out there. :) So, here we go:
#include <iostream>
template< bool IsLeafClass = true >
class AbstractBase
{
public:
AbstractBase() {
if ( IsLeafClass )
std::cout << "AbstractBase" << std::endl;
}
};
template< bool IsLeafClass = true >
class Base : AbstractBase< false > {
public:
Base() {
if ( IsLeafClass )
std::cout << "Base" << std::endl;
}
};
typedef Base<> CBase;
template< bool IsLeafClass = true >
class Derived : public Base< false > {
private:
CBase _base;
public:
Derived() {
if ( IsLeafClass )
std::cout << "Derived" << std::endl;
}
};
typedef Derived<> CDerived;
template < bool IsLeafClass = true >
class DerivedMore : public Derived< false > {
private:
CDerived _derived;
CBase _base;
public:
DerivedMore() {
if ( IsLeafClass )
std::cout << "DerivedMore" << std::endl;
}
};
typedef DerivedMore<> CDerivedMore;
int main()
{
std::cout << "logging for b" << std::endl;
CBase b;
std::cout << std::endl << "logging for d" << std::endl;
CDerived d;
std::cout << std::endl << "logging for dm" << std::endl;
CDerivedMore dm;
}

Actually, there is a way, but in this case, only thanks to the fact that the base classes are using the std::cout stream directly. One possible solution is to inherit std::streambuf class like this:
#include <iostream>
#include <streambuf>
class DummyStreambuf : public std::streambuf {};
This step is needed because std::streambuf constructor are protected. When you have DummyStreambuf (or whatever you name it), all you need to do is to change stream buffer on std::cout standard stream.
int main()
{
DummyStreambuf dummy;
std::cout << "test" << std::endl;
// save default stream buffer for later use
std::streambuf *buff = std::cout.rdbuf(&dummy);
// this line shouldn't print
std::cout << "test" << std::endl;
// restore default stream buffer
std::cout.rdbuf(buff);
std::cout << "test" << std::endl;
}
Of course, there is room for improvement here. You could write a simple singleton which could turn on and off std::cout output. Here is one possible implementation for single-threaded environment:
#include <iostream>
#include <streambuf>
class DummyStreambuf : public std::streambuf {};
class CoutSwitch
{
private:
DummyStreambuf _dummyBuf;
std::streambuf *_coutBuf;
CoutSwitch() : _coutBuf( std::cout.rdbuf() ) {}
static CoutSwitch &instance() {
static CoutSwitch _instance;
return _instance;
}
public:
static void turnOn() {
std::cout.rdbuf( instance()._coutBuf );
}
static void turnOff() {
std::cout.rdbuf( &instance()._dummyBuf );
}
};
int main()
{
std::cout << "test" << std::endl;
CoutSwitch::turnOff();
std::cout << "test" << std::endl;
CoutSwitch::turnOn();
std::cout << "test" << std::endl;
}

Related

Nested struct attributes inheritance

I read that you can extend a structure by using inheritance. I have a derived class in which I want to have the same struct that its parent but extended with more fields. This seems to work, however when I call a method from the Parent class that modified the structure, it does not have effect in the Child structure attribute. Here, an example of what am I trying:
class Parent
{
public:
struct info
{
int a;
};
info data;
virtual void main(void);
};
void Parent::main()
{
data.a =1;
}
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
info2 data;
virtual void main(void);
};
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << data.a << "\n";
std::cout << data.b << "\n";
}
int main(void)
{
Parent *base;
Child derived;
base = &derived;
base->main();
return 0;
}
This instead of printing 1 and 2 prints 0 and 2. So basically as if the attribute data from the derived class is not modified by the call to Parent::main.
What the right way of doing that? Am I completely doing it wrong?
You mean
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << Parent::data.a << "\n";
std::cout << data.b << "\n";
}
The name data declared in the derived class hides the name data declared in the base class. So you need to use a qualified name to access a hidden member of the parent class.
As for data member a of the member data of the derived class then it was not initialized.
Objects of the derived class have two data members data: one is inherited with the type info (which name is hidden in the derived class) and other is the own data member of the derived class.
The base class knows nothing about the data member data of the derived class.
You could define a virtual function within the class info. For example
#include <iostream>
class Parent
{
public:
struct info
{
int a;
virtual void set( int a )
{
this->a = a;
}
};
info data;
virtual void main(void);
};
void Parent::main()
{
data.set( 1 );
}
class Child: public Parent
{
public:
struct info2: public info
{
int b;
void set( int a ) override
{
this->a = a;
}
};
info2 data;
virtual void main(void);
};
void Child::main(void)
{
data.set( 3 );
data.b = 2;
std::cout << data.a << "\n";
std::cout << data.b << "\n";
}
int main(void)
{
Parent *base;
Child derived;
base = &derived;
base->main();
return 0;
}
The program output is
3
2
You're entirely correct, Parent::main() is unable to access Child::data, and knows nothing about any mythical info2 type; to it, Parent::data is all there is, and info is its type.
There are a few easy ways to make Child::main() work with Child::data instead of Parent::data, or to make it access the desired field from each version, but I suspect that's not what you're after. If you want both Parent and Child to see the same data (as an info and an info2, respectively), then data should itself be used polymorphically. For this example, I'll use a regular pointer for simplicity (and in turn, operator. will be replaced with operator->, when accessing data's members), but I would recommend looking into smart pointers such as std::unique_ptr to simplify the memory management.
class Parent
{
public:
struct info
{
int a;
// Chances are, it's going to be deleted through an info* no matter what it is. Therefore, virtual destructor.
virtual ~info() = default;
};
info* data; // Consider using a smart pointer here, like std::unique_ptr.
virtual void main(void);
virtual void output() const; // Just adding this for convenience.
// Default constructor now allows data to be supplied, or creates it if necessary.
Parent(info* dp = nullptr) : data(dp ? dp : new info) {}
// Correct destructor will always be called.
virtual ~Parent() { if(data) { delete data; } }
};
void Parent::main()
{
data->a =1;
}
We now remove the field Child::data, and instead have Child supply its desired data to Parent's constructor.
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
//info2 data;
virtual void main(void);
void output() const override; // Just adding this for convenience.
Child() : Parent(new info2) {}
};
Child will, when required, view data as an info2 instead of an info.
void Child::main(void)
{
Parent::main();
auto dataPtr = static_cast<info2*>(data); // In Child, we know data is an info2*.
dataPtr->b = 2;
// Just gonna move these to output(), for a cleaner illustration.
//std::cout << "Data->a: " << data->a << "\n";
//std::cout << "Data->b: " << dataPtr->b << "\n";
}
This will then cause data to work as desired, with Parent and Child both having the correct type.
void Parent::output() const {
std::cout << "Parent:\n";
std::cout << "> Data->a: " << data->a << "\n";
}
void Child::output() const /*override*/ {
std::cout << "Child as ";
Parent::output();
auto dataPtr = static_cast<info2*>(data);
std::cout << "Child:\n";
std::cout << "> Data->a: " << dataPtr->a << "\n";
std::cout << "> Data->b: " << dataPtr->b << "\n";
}
This will then perform as expected, as seen live on Coliru. Note that if you want to be able to, e.g., create a Child from a pre-existing Parent, you'll want to add a move constructor that can make an info2 from an info; you should consider following the Rule of Five, or using a smart pointer instead of a raw pointer. ;P
You have to use the below code:
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << Parent::data.a << "\n";
std::cout << data.b << "\n";
}

Can changing an access specifier in a program change the behaviour of the program?

I wonder is there any cases in a C++ program wherein changing an access specifier (public/protected/private) in the code lead to a change in the behaviour of that program?
Templates allow you to do different things depending on whether a member or method is accesible or not. Just as a random example, consider this:
#include <type_traits>
#include <iostream>
struct foo_private {
private:
foo_private() {}
};
struct foo_public {
public:
foo_public() {}
};
int main() {
std::cout << std::is_default_constructible<foo_private>::value;
std::cout << std::is_default_constructible<foo_public>::value;
}
One interesting example that essentially happens purely at runtime, meaning a program needs to somehow know some information derived from access level: Per [except.handle]/3.2, an exception handler matches an exception object if the handler accepts an unambiguous and public base class of the exception object's class type.
#include <iostream>
class Base {};
void test(void (*thrower)()) {
try {
thrower();
} catch (Base&) {
std::cout << "Caught a Base." << std::endl;
} catch (...) {
std::cout << "Not a Base?" << std::endl;
}
}
class D1 : public Base {};
class D2 : private Base {};
int main() {
std::cout << "Test D1" << std::endl;
test([]() { throw D1{}; });
std::cout << "Test D2" << std::endl;
test([]() { throw D2{}; });
}
This prints:
Test D1
Caught a Base.
Test D2
Not a Base?
... even though the only difference between D1 and D2 is a change of an access specifier keyword.
Yes, this can happen if someone SFINAE'd off of calling that function. For example:
class Cat {
public:
void purr() const;
public:
void hiss() const;
};
using prefer_overload_t = int;
using backup_overload_t = long;
template <typename T>
auto react(prefer_overload_t, T const& t)
-> decltype(t.purr())
{
return t.purr();
}
template <typename T>
void react(backup_overload_t, T const& t)
{
t.hiss();
}
int main() {
Cat cat;
react(prefer_overload_t{}, cat);
}
Live on Godbolt.
If the purr function has public accessibility, this calls cat.purr().
If the purr function has non-public accessibility, this calls cat.hiss().

Is it possible to replace a parent class?

If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.

Disallow slicing to keep multiple parent class properties in sync

I am deriving an object from two parent classes. These two parents each have different types of properties, but I want the child to keep them in sync with each other. However, I want to disallow users of the library from treating Child like a ParentA or a ParentB accidentally via slicing. For example:
#include <iostream>
class ParentA
{
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class ParentB
{
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class Child : public ParentA, public ParentB
{
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
ParentA::modify();
ParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
This call to Change(child); calls ParentA's modify() function, in which the ParentA properties can get out of sync with the ParentB properties, leaving the Child in a bad state.
There are many functions (the read*() ones here) in ParentA and ParentB that I don't want to have to manually forward from Child, so I can't derive privately.
Is there a way to make this call to Change(child) produce a compiler error (without changing the signature of Change)?
There is in fact a way to do this (although said you didn't like it): private or protected inheritance is the C++ mechanism to achieve what you want.
Bear in mind that since your child class is trying to keep some sort of invariant between A and B, if you inherit publicly, someone will find a way to use A or B's interface to violate the invariant anyway so you need to protect against those being used in the child directly, which the restricted inheritance does perfectly.
If there are then some methods in the parent that don't affect the two-class invariant you can using those down into the public section of Child.
As the comments already say the cleanest way might be to just inherit from ParentA and ParentB with private and forward the needed functions.
I had another idea: You could extract the functionality of ParentA and ParentB into 2 abstract classes (AbstractParentA,AbstractParentB) and use these classes as base classes.
This would give you the desired behaviour:
#include <iostream>
class AbstractParentA
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class AbstractParentB
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class ParentA : public AbstractParentA
{
virtual void no_instance() override {}
};
class ParentB : public AbstractParentB
{
virtual void no_instance() override {}
};
class Child : public AbstractParentA, public AbstractParentB
{
virtual void no_instance() override {}
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
AbstractParentA::modify();
AbstractParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
error C2664: 'void Change(ParentA)': cannot convert argument 1 from 'Child'
note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

boost::shared_ptr, access to a variable after inheritance?

I use MonkSVG library:
goal file
A class object is defined as:
//mkSVG.h
namespace MonkSVG {
using namespace std;
class SVG;
class ISVGHandler {
public:
typedef boost::shared_ptr<ISVGHandler> SmartPtr;
...
ISVGHandler::SmartPtr _handler;
...
Then the author of this library defines another class:
class OpenVG_SVGHandler : public ISVGHandler
And it is possible to access to variables of ISVGHandler via _handler from SVG.
I inherited my 2 own classes: the first one from ISVGHandler and the second one is from SVG, and the first one has its own variables, but I can't get access to them directly. The only solution I found is to create a setter-getter methods, but even so I need to define them in both root class and the last inherited class.
Are there any better solutions?
You are supposed to define your own handler using ISVGHandler, but to add and use new functions, you are making a derived SVG as well. Your SVG has to have your handler to work, so you can either make them both at the same time, or have initialize check it for you just to be sure.
#define MAKE_YOUR_OWN_HANDLER
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
// darned compiler not up to date
#define nullptr NULL
class ISVGHandler {
protected:
ISVGHandler(){} // interface, must be derived
public:
virtual ~ISVGHandler(){}
typedef boost::shared_ptr<ISVGHandler> SmartPtr;
void onPathBegin() {std::cout << "base onPathBegin" << std::endl;}
void onPathEnd() {std::cout << "base onPathEnd" << std::endl;}
};
class OpenVG_SVGHandler : public ISVGHandler {
public:
typedef boost::shared_ptr<OpenVG_SVGHandler> SmartPtr;
static ISVGHandler::SmartPtr create() {
return boost::make_shared<OpenVG_SVGHandler>();
}
void draw() {std::cout << "openvg draw" << std::endl;}
void optimize() {std::cout << "openvg optimize" << std::endl;}
};
class WrongHandler : public ISVGHandler {
public:
typedef boost::shared_ptr<OpenVG_SVGHandler> SmartPtr;
static ISVGHandler::SmartPtr create() {
return boost::make_shared<WrongHandler>();
}
void draw() {std::cout << "openvg draw" << std::endl;}
void optimize() {std::cout << "openvg optimize" << std::endl;}
};
class SVG {
public:
virtual ~SVG(){}
bool initialize(ISVGHandler::SmartPtr handler) {
_handler = handler;
std::cout << "base init" << std::endl;
return true;}
void onPathBegin() {_handler->onPathBegin();}
void onPathEnd() {_handler->onPathEnd();}
private:
ISVGHandler::SmartPtr _handler;
};
class OpenVG_SVG : public SVG {
private:
OpenVG_SVGHandler * m_pOpenVG_Handler;
public:
#ifdef MAKE_YOUR_OWN_HANDLER
OpenVG_SVG(){
// use factory to make correct handler
ISVGHandler::SmartPtr spBaseHandler (OpenVG_SVGHandler::create());
// store known handler type for this class to use
m_pOpenVG_Handler = reinterpret_cast<OpenVG_SVGHandler*>(spBaseHandler.get());
// initialize the SVG base class
initialize(spBaseHandler);
}
#else
OpenVG_SVG() : m_pOpenVG_Handler(nullptr) {}
bool initialize(ISVGHandler::SmartPtr handler){
try {
m_pOpenVG_Handler = dynamic_cast<OpenVG_SVGHandler*>(handler.get());
if (m_pOpenVG_Handler){
std::cout << "openvg svg init" << std::endl;
return SVG::initialize(handler);
} else {
std::cout << "wrong handler" << std::endl;
}
} catch (std::exception &e){
std::cout << "wrong handler: " << e.what() << std::endl;
}
return false;
}
#endif
// write functions that are OpenVG specific in this class, using m_pOpenVG_Handler
void draw() { m_pOpenVG_Handler->draw(); } // I'd check for null but that's not relevant to the question
void optimize() {m_pOpenVG_Handler->optimize(); }
// let the virtual functions handle all the other behavior.
};
int test_svg()
{
OpenVG_SVG ovg;
#ifndef MAKE_YOUR_OWN_HANDLER
ovg.initialize(OpenVG_SVGHandler::create());
#endif
ovg.draw();
ovg.onPathBegin();
ovg.onPathEnd();
ovg.optimize();
#ifndef MAKE_YOUR_OWN_HANDLER
std::cout << "attempting to initialize with wrong handler:" << std::endl;
OpenVG_SVG bad;
if (bad.initialize(WrongHandler::create())){
bad.draw();
}
#endif
return 0;
}