Here is the idea: I have a class that has some member variable(s), say x. This class also has a method, A(), which does not modify the member variable(s), but returns info about them. There is also a method B() which does modify the member variable(s). So basically, this is the setup:
class Class
{
int x;
Class(int x) : x(x) { }
int A() { return x; /* info about x */ }
void B() { x++; /* updates x! */ }
}
So far so good. But now I want to have some special version of this class that will be used throughout the project, and I want it to have a specific set of member variable(s), say, x = 3. My idea was to add a const static Class mySpecialCase member to Class, and just refer to Class::mySpecialCase whenever necessary.
The problem however, is that I need to call A() on this object, to fetch some information, but do not want B() to be called on this object, since it would modify x, which would affect all future usage of the 'special case'.
Any ideas on how to solve this?
It's already illegal to call Class::mySpecialCase.B(), since mySpecialCase is const and B() is not a const member. You just need to make it possible to call A(), by making A() a const member function:
class Class
{
int x;
public:
Class(int x) : x(x) { }
static const Class mySpecialCase;
int A() const { return x; /* info about x */ }
void B() { x++; /* updates x! */ }
};
// In class.cpp:
const Class Class::mySpecialCase{3};
The problem however, is that I need to call A() on this object, to fetch some information, but do not want B() to be called on this object, since it would modify x,
Declare the object and B() as const but not A():
class Class {
public:
[...]
int A();
void B() const;
};
// Initialize const object.
const Class specialCase(3);
Calling specialCase.A() will be a compile error, but specialCase.B() is still okay because the const modifier indicates to the compiler this method does not alter the object.
So far so good.
Not really. A should be const:
int A() const { return x; /* info about x */ }
But now I want to have some special version of this class
By version, you mean instance, right?
Add a static member function returning a reference to a static local instance of Class:
#include <iostream>
class Class
{
public:
int x;
Class(int x) : x(x) { }
int A() const { return x; /* info about x */ }
void B() { x++; /* updates x! */ }
static Class &SpecialInstance()
{
static Class instance(3);
return instance;
}
};
int main()
{
Class a(1);
Class b(2);
Class c = Class::SpecialInstance();
std::cout << c.A() << "\n";
}
Related
I have a base product class with a few private members and a public getter that derived classes inherit. I would like to disqualify instantiation, since the class is intended for use with an abstract factory. I thought protected con/destructors might work, however, this breaks my smart pointers. Friending seems like a useful disaster. Is there a well-known solution to this, or should I resign myself to the fact that any client who has the factory injected must also know enough to instantiate the base product?
class Product
{
private:
char type_name;
char size_name;
public:
Product(char, char);
virtual ~Product() {}
void Print();
};
Use a token key.
private:
Product(char, char);
struct key_t{explicit key_t(int){}};
static key_t key(){return key_t(0);}
public:
Product(key_t, char a, char b):Product(a,b){}
static std::shared_ptr<Product> make_shared(char a, char b){ return std::make_shared<Product>(key(),a,b); }
anyone with a Product::key_t can construct a Product without being a friend. And without the key, you cannot.
This lets Product pass creation-rights as a value.
Smart pointers with configurable destroy code can use similar techniques. But I'd just make the destructor public.
Your static member function, or friend function, which is the factory should have no problem with calling protected constructors and returning a smart pointer. Generally plan to return a std::unique_ptr<BaseClass> which can be converted into a std::shared_ptr if the caller wants that instead.
Make the virtual destructor public.
Update: Don't bother making the factory a friend. You only need to prevent the construction of the base and intermediate classes. Make them effectively hidden and private by hiding the implementation classes in their own source file. Or an anonymous namespace I suppose.
Here have some code of how I would do it:
#include <iostream>
#include <memory>
#include <string>
// ITest is the only class any other code file should ever see.
class ITest {
protected:
ITest() = default;
public:
virtual ~ITest() = 0;
virtual int getX() const = 0;
virtual int getY() const = 0;
};
// Destructors must always have an implementation even if they are pure virtual.
ITest::~ITest() {}
std::ostream &operator<<(std::ostream &os, const ITest &x) {
return os << '[' << x.getX() << ',' << x.getY() << ']';
}
// Declaration of constructTest factory function.
// Its definition should be hidden in a cpp file.
std::unique_ptr<ITest> constructTest(int x);
// The main function does not need to know anything except the ITest interface
// class and the constructTest function declaration.
int main(int argc, char *argv[]) {
int val = 0;
if (argc > 1)
val = std::stoi(argv[1]);
auto p = constructTest(val);
std::cout << *p << std::endl;
}
// These classes should be defined in a private header file or in a cpp file.
// Should not be visible to any other code. It has no business knowing.
// Hiding all of this implementation is sort of the point of abstract interface
// classes and factory function declarations.
class TestBase : public ITest {
private:
int x = 0;
int y = 0;
protected:
TestBase(int x = 0, int y = 0) : x(x), y(y){};
public:
int getX() const override { return x; }
int getY() const override { return y; }
};
class TestA final : public TestBase {
public:
TestA() = default;
};
class TestB final : public TestBase {
public:
TestB(int x, int y) : TestBase(x, y) {}
int getX() const override { return -TestBase::getX(); }
};
std::unique_ptr<ITest> constructTest(int x) {
// make_unique is c++14.
// For C++11 use std::unique_ptr<ITest>(new TestB(x, x)
if (x) {
return std::make_unique<TestB>(x, x);
// return std::unique_ptr<ITest>(new TestB(x, x));
}
return std::make_unique<TestA>();
}
The answer was to make the destructor a pure virtual AND to implement it with an empty body. That empty implementation is where I got tripped up. Print() doesn't need to be static.
Product.hpp
#include <memory>
class Product {
public:
virtual ~Product() = 0;
void Print();
protected:
char type_name{};
char size_name{};
private:
};
Product.cpp
#include "Product.hpp"
Product::~Product() {}
void Product::Print() {
//Print p
}
Im writing embedded code that cannot use memory allocation!
Also, static objects (therefore constructed before the microcontroller has executed the main funtion with all its initialization) shall be constructed within the main after the initialization, not before.
The only solution people suggest is to use static object pointers and allocate (construct them with new) during initialization. since this is no option for me, is there no other solution?
what i wanna do is as follows:
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
}
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
void init()
{
// now i wanna construct myObjectA
myObjectA(123, false);
}
private:
char myChar1;
A myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
}
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
You can use a storage area large enough to create there an instance of A and placement new to control the time you create it.
As an example:
#include
#include
struct A {
A(int a, bool b): myVal1(a), myVal2(b) {}
void foo() {}
private:
int myVal1;
bool myVal2;
};
struct B {
B(char x): myChar1(x) {}
~B() { if(ptr) { ptr->~A(); } }
void init() {
ptr = new (&storage) A{123, false};
}
A * myObjectA() {
return ptr;
}
private:
char myChar1;
std::aligned_storage_t<sizeof(A), alignof(A)> storage;
A *ptr{nullptr};
};
static B myObjectB('F');
void global_init() {
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main() {
global_init();
myObjectB.myObjectA()->foo();
}
This won't allocate memory (if I got right what you mean for that) and the instance of A is actually created within B::init (that seems to be a requirement from what you wrote in your question).
If you have access to a compiler that supports C++17 or you can use the C++ Boost Libraries, std::optional is a valid alternative as suggested in another answer. Anyway you didn't specify the revision of the standard to which to adhere, so... Here is a way to go in any case.
Do you have boost available?
#include <boost/optional.hpp>
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
};
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
A& getA() {
assert(myObjectA);
return myObjectA.get();
}
void init()
{
// now i wanna construct myObjectA
myObjectA.emplace(123, false);
}
private:
char myChar1;
boost::optional<A> myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
};
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main()
{
global_init();
}
I want to count the number of calls to a certain function in class A, made by another function in class B. This is done in a class test for class B, and in this test class A is stubbed.
Here I try to explain the involved classes in terms of C++ code:
class X
{
const void Method() const = 0;
}
class A : public X
{
const void Method() const;
}
class AStub : public A
{
const void Method() const;
U32 getNumberOfCallsToMethod();
}
class B
{
void runAlgorithm();
A* getA(); // returns pointer to the A instance used by B
}
class BTest
{
void test_runAlgorithm()
{
B b;
// b is setup to use a stub of A rather than A..
// ...
U32 before = ((AStub*)b.getA())->getNumberOfCallsToMethod();
b.runAlgorithm();
U32 after = ((AStub*)b.getA())->getNumberOfCallsToMethod();
// Verify that Method() has been run exactly once
ASSERT_EQUAL("Unexpected number of calls to Method()",
before + 1, after);
}
}
Now to my problem. How do i override Method() in my stub with a "dummy" variant that counts number of calls? I have the dummy in place and it is called as intended, but i cannot make it increment a counter because it is declared const. I would like to add a counter to my AStub and have AStub::Method() increase the counter as part of the dummy implementation, but this seems tricky given the way it is declared.
I cannot use any mocking frameworks like google mock or similar, but there has to be some common solution to this issue. How would one normally go about this little hurdle?
Thanks
If you are using inheritance, you'll probably need to declare Method as virtual:
class X
{
virtual void Method() const = 0;
};
(Also removed const void, as it makes no sense - const after the member function is sufficient to make it a const function)
Then use the mutable keyword to tell the compiler "I want this particular member variable to be able t change even when in a const call" - call this variable numCalls, adding a default constructor to zero numCalls.
class AStub : public A
{
public:
AStub() : numCalls(0) {}
void Method() const;
U32 getNumberOfCallsToMethod();
private:
mutable U32 numCalls;
}
Finally, do the implementation of Method which increments number of calls and then calls the original function:
void AStub::Method() const
{
numCalls++;
A::Method();
}
If the question is how to modify a member variable in a const method, then the answer is quite simple : use the mutable keyword.
Something like this should work :
class AStub : public A
{
public:
const void Method() const{ ++n; }
mutable int n;
};
You can use a mocking framework to do the job for you. No need to implement your own mock class (AStub).
Here is how you do it with Fake-It. A simple mocking framework for C++:
class X
{
public:
virtual const void foo() const = 0;
};
class A : public X
{
public:
virtual const void foo() const override {}
};
class B
{
A& _a;
public:
B(A& a):_a(a){}
void runAlgorithm() { _a.foo(); }
A& getA() { return _a; }
};
A a;
Mock<A> mock(a);
Spy(Method(mock,foo)); // Spy A::foo on the mock object.
// Instantiate B (class under test) and inject the mock instance.
B b(mock.get());
// Run the tested method.
b.runAlgorithm();
// Verify the A::foo of the injected object was invoked exactly once.
Verify(Method(mock,foo)).Exactly(Once);
Please check the following code. Why it is wrong and how to fix? Thank you.
class A
{
public:
class B
{
public:
B(int(*cf)())
{
f = cf;
}
int (*f)();
};
B *b;
A()
{
b = new B(this->a);
}
int a()
{
}
};
int main()
{
A a;
}
compilation error:
If you absolutely need to call a function by pointer you will need to use a pointer to member function instead of a pointer to function. A pointer to member function has a different declaration syntax that includes the class type the function belongs to. In your case the parameter declaration would look like int (A::*cp)(). You will also need to change the declaration of the f member variable to int (A::*f)().
In order to call a pointer to member function you need to have a pointer to an object of the type the function belongs to. You also need to use one of the pointer to member operators; ->* or .*
void call(A* c, int (A::*f)())
{
(c->*f)(); // call member function through pointer
}
The extra set of parenthesis is required due to the order of precedence of operators.
The following code includes the changes necessary for you to use pointer to member functions.
class A
{
public:
class B
{
public:
// Take a pointer to member function.
B(int(A::*cf)())
{
f = cf;
}
void call(A* c)
{
(c->*f)();
}
int (A::*f)(); // pointer to member function
};
B *b;
A()
{
b = new B(&A::a);
}
int a()
{
return 0;
}
};
int main()
{
A a;
a.b->call(&a);
}
I also recommend that you consider using std::function and std::bind (or their Boost equivalents if you do not have a C++11 compiler).
Do not use function pointers in the first place when using C++.
There is an easier and more elagant solution - an interface.
i.e.
class Interface {
public:
virtual int CallMe() = 0;
};
class B : public Interface { int CallMe() { return 5; };
class A : public Interface {
private:
Interface *m_i = 0;
public:
A(Interface *i) : m_i(i) { }
A() : m_i(this) { };
void DoIt() { cout << m_i->CallMe() << endl; }
int CallMe() { return 8; }
};
int main() {
A a(new B); // Coult be any object that implements Interface (as yes it is a memory leak
A aa();
a.DoIt(); // Will print 5
aa.DoIt(); // WIll print 8
return 0;
}
I'm writing a C++ code which should populate a screen (and it's behaviour) based on a function from the object pointer was initiated with. Let's better show it on a code:
class A:parentClass {
public:
int X () {return 5;}
}
class B:parentClass {
public:
int X () {return 3;}
}
class C:parentClass {
public:
int X () {return 1;}
}
main {
parentClass *p;
p = new A;
printf("%d\n,p.x); //to return 5
delete p;
p = new B;
printf("%d\n,p.x); //to return 3
}
I'm getting something like this on compilation:
‘class parrentClass’ has no member named ‘x’
I know that this is wrong, as parrentClass simply doesn't have that member, but I don't have an idea how to solve this. I tried to go through templates, but I'm not getting anywhere.
I also tried to replace "parentClass *p;" with "int *p;", but then I'm getting:
cannot convert ‘CardsFrame*’ to ‘int*’
Thanks for your suggestions in advance,
Jan
You need to declare the X() method virtual on the parent class for this to work:
class ParentClass
{
public:
virtual int X();
};
To be clear: the following is a complete working example (compiled with gcc):
#include <iostream>
class ParentClass {
public:
virtual int x() = 0;
};
class A : public ParentClass {
public:
int x() { return 5; }
};
class B : public ParentClass {
public:
int x() { return 3; }
};
class C : public ParentClass {
public:
int x() { return 1; }
};
int main() {
ParentClass *p;
p = new A;
std::cout << p->x() << std::endl; // prints 5
delete p;
p = new B;
std::cout << p->x() << std::endl; // prints 3
delete p;
}
You really need to get your basics right as your syntax is all wrong. You need to use p->X() to call the function. And to answer the actual question make X() virtual in the base class.
printf("%d\n,p.x); //to return 5
should be:
printf("%d\n,p->X()); //to return 5
Also, X() should be virtual in the Base class.