#include <iostream>
using namespace std;
//can't modify it
class Orig{
public:
void Method(){
cout << "I am original method";
}
};
class Mock{
public:
void Method(){
cout << "I am mock method";
}
};
//can't modify it
class UseMethod{
Orig object;
public:
void UseOrigMethod(){
object.Method();
}
};
class UseMethodMock : public UseMethod{
//some code
};
int main()
{
UseMethodMock o;
o.UseOrigMethod();
}
I want to call Method() of Mock class using above code when I call o.UseOrigMethod(); from main. I have tried declaring object of Mock class in UseMethodMock but still it uses Orig's object.
Is there any way we can fool compiler and call Mock's Method when it calls object.Method() in UseMethod class?
I can change code in Mock and UseMethodMock classes but not in others.
There is no shame in modifying code to make it more testable, so maybe you can reconsider. In this case:
Prepare Orig for inheritance by making its methods virtual.
Inject an Orig instance into UseMethod via its constructor (beware slicing – pass by pointer or reference).
Have Mock inherit from Orig and override the virtual methods.
If the performance of virtual calls is a concern, do it all at compile time:
Make UseMethod a template, that takes the type of Orig as a template parameter.
In production code, use UseMethod<Orig>.
In test code, use UseMethod<Mock>.
If you really, absolutely, positively can definitely, certainly not modify Orig and UseMethod, you can abuse the preprocessor:
#include "Orig.h"
#define Orig Mock
#include "UseMethod.h"
#undef Orig
Of course, this comes with a whole boatload of caveats (most notably, it assumes that UseMethod.cpp does not refer explicitly to the Orig type), and in general I would strongly advise against it.
Because you call orig's method. You should override useOrigMethod() in UseMethodMock class.
you just need to change the UseMethod class Orig object to Moke object i will give expected output it means called the method of Moke class.
code:
#include <iostream>
using namespace std;
//can't modify it
class Orig{
public:
void Method(){
cout << "I am original method";
}
};
class Mock{
public:
void Method(){
cout << "I am mock method";
}
};
//can't modify it
class UseMethod{
//need to change here Orig to Moke
Mock object;
public:
void UseOrigMethod(){
object.Method();
}
};
class UseMethodMock : public UseMethod{
//some code
};
int main()
{
UseMethodMock o;
o.UseOrigMethod();
}
output
I am mock method
--------------------------------
Process exited after 0.006435 seconds with return value 0
Press any key to continue . . .
Related
Streamlined Example of the problem:
#include <string>
#include <deque>
#include <iostream>
class Action{
public:
std::string name;
Action(std::string name){
this->name = name;
}
};
class Ability : public Action{
public:
int bar;
Ability(std::string name) : Action(name){}
};
int main(){
std::deque<Action*> foo;
Ability test("asdf");
test.bar = 122;
foo.push_back(&test);
std::cout << foo.at(0)->bar << std::endl;
return 0;
}
This creates an error, that there is no 'bar' member of 'Action'.
I realise that this relates to object slicing and I've attempted to use pointers, which allows the vector to push back the 'Ability' object but I cannot access its 'bar' member.
What am I missing?
First, a word from our sponsor: What is object slicing?
Now that you've read the above link, you can see that no slicing has taken place because the object was not copied into foo, only a pointer to the object was copied. The Ability is still intact, wherever in memory test sits.
But... Foo contains pointers to Action, not Ability. There is no way for a user of Foo to know if any given element of Foo is a reference to an Action, an Ability, or some other subclass of Action that they know absolutely nothing of. Very powerful stuff, the ability to work with something you don't even know exists, but this comes at a price: You have to work with it as something you do know. Users of Foo can only use the interface presented to them, that of Action. There are ways around this, such as dynamic_cast, but in most cases it best to stick with the provided interface and allow an overloaded method or operator to do black magic behind the scenes to do the correct thing for whatever the Action represents. If this means you have to
class Action{
public:
std::string name;
Action(std::string name){
this->name = name;
}
virtual int getbar() = 0; // pure virtual method that all subclasses
// of Action must implement
};
class Ability : public Action{
public:
int bar;
Ability(std::string name) : Action(name){}
int getbar()
{
return bar;
}
};
and later
std::cout << foo.at(0)->getbar() << std::endl;
so be it.
What are the advantages or disadvantages of using a class declaration with pure virtual methods over using one with undefined members? Example:
Pure virtual functions
TestClass.h
namespace test {
class TestClass {
virtual void DoSomething() = 0;
}
}
TestClass.cpp
namespace test {
class TestClassImpl : public TestClass {
void DoSomething() {
std::cout << "Hello!" << std::endl;
}
}
}
Undefined methods
TestClass.h
namespace test {
class TestClass {
void DoSomething();
}
}
TestClass.cpp
namespace test {
void TestClass::DoSomething() {
std::cout << "Hello!" << std::endl;
}
}
I know that virtual function calls in C++ have an overhead due to indirection and extra branching, but for now these overheads don't concern me. I'm more interested in having extensible, correct code (FYI: I am a C++ newb, but not a programming newb).
They have completely different uses, therefore you should not treat them the same or try to compare them.
A pure virtual method means that a derived class must implement that method itself for it to be complete. This will usually be used like this:
Object.hpp
class Object{
public:
virtual void use() = 0;
};
class Banana: public Object{
public:
void use(){std::cout << "You ate the Banana! Good work." << std::endl;}
};
class Rock: public Object{
public:
void use(){std::cout << "You use the Rock. Nothing happens." << std::endl;}
};
So that later on you can refer to instances of Rock or Banana as Objects and know that they will have a use function.
E.g.
main.cpp
#include "Object.hpp"
int main(){
std::vector<Object*> objects;
Banana banana;
Rock rock;
objects.push_back(&banana);
objects.push_back(&rock);
for(const Object *o : objects)
o->use();
}
If you decide not to use virtual functions, then you can't treat the objects as Objects, per se.
E.g.
main.cpp
class Banana{
public:
void use();
};
class Rock{
public:
void use();
};
int main(){
std::vector<???> objects;
Banana banana;
Rock rock;
objects.push_back(&banana); // can't do
objects.push_back(&rock); // or this
for(const ??? *o : objects)
o->use(); // and definitely not this
}
If you try to do this by just delegating your implementations of functions into a different code unit, well, I don't know what you will be trying to do.
You could actually implement your virtual functions in another file, just so long as you do implement them; otherwise when trying to access that kind of object as an Object you will get errors.
You would want to use functions with outside implementations when dealing with things like libraries and very large projects. You do this so that for every translation of the code you don't have to compile that function again, just call to the already implemented code :D
This makes build times hella shorter.
I want to transfer a function pointer in the constructor but get some error Messages...
I my parent class I declared:
class Strip{
public:
typedef void(Strip::*LOG)(const std::string&);
with a function log(const string&)
In my child class I forward declare Strip with class Strip and have somthing like that
class Observable{
public:
Observable(const char &signal,Strip::LOG log,const QCustomPlot *plot);
with a parameter
Strip::LOG log;
When I try to compile I get the error's
Strip::LOG has not been declared
and LOG in class Strip does not name a type
Any Idea how to fix that?
So passing a pointer to a member function presents several issues:
It's a member function as such it will need to have an instance of the class passed into it to work (the implicit this parameter).
It doesn't prevent the class you're passing it to from knowing about the class the function pointer originates so you gain nothing in terms of hiding.
A better way is to declare an Interface and pass that
// ILogger.hpp
// should be completely virtual
struct ILogger{
virtual void log(const ::std::string&) = 0;
};
// Strip.cpp
class Strip : public ILogger{
public:
void log(const ::std::string& data){
// does something
}
};
// Observable.cpp
#include "ILogger.hpp"
class Observable{
public:
Observable(ILogger* logger);
};
// some other file that knows about and constructs both
// has to be a pointer allocated to new to make the Vtables work
::std::unique_ptr<Strip> s(new Strip());
// pass in the pointer to an instance of a class that implements ILogger
Observable observed(s.get());
Using an interface means you can completely abstract the two classes apart and Observable need not know anything about the instance being passed to it other than it implements ILogger. Internally Observable can call the logger by just calling logger->log.
May be this code can be usefull (compiled w/o errors):
#include <iostream>
using namespace std;
class Strip{
public:
typedef void(Strip::*LOG)(const std::string&);
void log(const string& s)
{
cout << "log() called\n";
}
};
class Observable{
public:
Observable( Strip::LOG l )
{
Strip s;
(s.*l)("string");
}
};
int main() {
Strip::LOG log = &Strip::log;
Observable o( log );
return 0;
}
http://ideone.com/RD4K1r
Browsing in a code base I found something on the line of:
class Interface{
public:
virtual void func() = 0;
};
class Implementation : public Interface{
protected:
void func() override {};
};
I thought that would have been a compilation error, but it seems it is not. What sense does it make?
In C++:
accessibility is a “static” notion (checked at compile-time), whereas
virtual dispatch is a “dynamic” notion (the implementation to call is chosen at run-time).
We can say that C++ keeps those two notions “orthogonal”.
So with your example, this will compile (not realistic code, just illustration):
Implementation obj;
Interface& ref = obj;
ref.func(); // (will call obj.func())
but this won't:
Implementation obj;
obj.func(); // error: Implementation::func is protected
effectively “forcing” you to only use the interface (which maybe was the intent). — Edit: see Dieter Lücking's answer for a maybe better design.
Freedom. Sometimes it may be kind of useful (for example if you want to hide a member you want to discourage to be used). At least when they access through derived class.
See it as kind of "explicit implementation". Let's say, for example, you have a base interface List like this (very simplified code for illustration purposes):
class List {
public:
virtual void add(std::string item) = 0;
virtual std::string at(int index) = 0;
};
You create your ReadOnlyList concrete class which implements List interface, in this case you would discourage users of your class to call add() method, just change its visibility. Unless they're accessing it through List interface it'll be hidden.
Another example? If you want to provide an interface for some specific tasks but it's an implementation detail and it's not part of class contract. In this case you make them protected or private and they won't be accessible.
That said it's so weak and confusing that I would avoid to do it, besides very few, commented and well controlled exceptions.
What sense does it make?
Yes, it makes sense. If you try to create object of Derived type, you will not be able to call that method. So the idea is to always access the object through it's interface.
The idea is to enforce the Interface segregation principle.
#include <iostream>
#include <vector>
#include <memory>
struct Base
{
public:
virtual ~Base(){}
virtual void foo() = 0;
};
struct Derived1 : Base
{
protected:
virtual void foo(){
std::cout << "foo 1" << std::endl;
}
};
struct Derived2 : Base
{
protected:
virtual void foo(){
std::cout << "foo 2" << std::endl;
}
};
void wouldFail()
{
Derived1 d;
// d.foo(); -- Error! Do not try to call it directly
}
void ok()
{
std::vector< std::shared_ptr< Base > > v;
v.emplace_back( std::make_shared<Derived1>() );
v.emplace_back( std::make_shared<Derived2>() );
for ( auto & it : v )
it->foo();
}
int main()
{
wouldFail();
ok();
}
I am trying to access a protected function in class Test but I have no idea how to do it.
Ok I admit one fact that I'm asking this because there's one part of my homework which I am tasked to put a function as protected: and access it instead of putting it to public:
and I am not sure how should I do it.
the code below is how I normally access a function but of course, it doesn't work since it's protected:
Test.h
#ifndef Test_Test_h
#define Test_Test_h
class Test {
protected:
void sampleOutputMethod();
};
#endif
Test.cpp
#include "Test.h"
void Test::sampleOutputMethod() {
std::cout << "this is a test output method" << std::endl;
}
main.cpp
#include Test.h
#include<iostream>
int main() {
Test test;
test.sampleOutputMethod();
}
There are essentially two ways of accessing a protected member:
1) Create a class that inherits from your class Test:
class Test2 : public Test {
public:
void sampleOutputMethod() { ::sampleOutputMethod; }
}
2) Create another class, and modify class Test to make the other class a friend of your Test class:
class Test; // Forward declaration of Test
class Test2 {
public:
void output( Test& foo ) { foo.sampleOutputMethod(); }
}
class Test {
protected:
void sampleOutputMethod();
}
A protected function is just as good as private function if you try to access it from a class that is not part of your hierarchy. You either have to make the class trying to access it a subclass of Test, or you have to declare it as friend class. I bet you need the first option.
You can delegate the function as well. Create a public function that calls the protected one.
This can be accomplished through either deriving Test or creating another class, Test2, and declaring Test a friend of Test2 and having Test2 contain an instance of Test.
Seeing all the instructions of your homework would help.
If you are allowed to modify class Test, you can add a public function which calls "sampleOutputMethod", or you can return function pointer of "sampleOutputMethod" using this trick https://stackoverflow.com/a/6538304/1784418