How to properly override virtual method to add functionality? - c++

In base class I have simple remove by id virtual function, however in derived class I need also emit a signal (notify) after removing.
In base class. Below is the default implementation of function
void Ui::GameEntityList::remove_games_by_sport_id_virt(const QString &sport_id)
{
for(QList<GameEntity*>::iterator it = m_game_list.begin();
it != m_game_list.end();)
{
GameEntity* tmp = (*it);
if(tmp->get_sport_id() == sport_id)
{
it = m_game_list.erase(it);
delete tmp;
tmp = 0;
}
else
{
++it;
}
}
}
In derived class. Overriding
void Ui::GameWidgetList::remove_games_by_sport_id_virt(const QString &id)
{
QList<GameEntity*>::iterator it;
for(it = m_game_list.begin(); it != m_game_list.end();)
{
GameWidget* tmp = dynamic_cast<GameWidget*>(*it);
Q_ASSERT(tmp != NULL);
if(tmp->get_sport_id() == id)
{
it = m_game_list.erase(it);
emit remove_game_in_monitor(tmp->get_id(), this->get_monitor_number()); // need to emit this signal
delete tmp;
tmp = 0;
}
else
{
++it;
}
}
this->set_number_of_games(m_game_list.size()); // need to call this function
}
I can't manage a way to avoid code duplication. Should I have an empty virtual notify() function and call it after removing an element? That way I can override notify() in derived to do the job. Is that an acceptable decision? Is implementing remove by id in base class unnecessary?

In your case, it is not that bad regarding amount of duplicated code. But, anyway, in situations like this, you may want to make this function non-virtual and move this customizable functionality to other virtual functions:
class GameEntityList
{
private:
virtual void on_erase(GameWidget* w)
{
//empty
}
virtual void on_finish(GameWidget* w)
{
//empty
}
//others
};
class GameWidgetList : public GameEntityList
{
private:
virtual void on_erase(GameWidget* w)
{
remove_game_in_monitor(w->get_id(), this->get_monitor_number());
}
virtual void on_finish(GameWidget* w)
{
this->set_number_of_games(m_game_list.size());
}
//others
};
And then:
void Ui::GameEntityList::remove_games_by_sport_id_virt(const QString &id)
{
QList<GameEntity*>::iterator it;
for(it = m_game_list.begin(); it != m_game_list.end();)
{
if(tmp->get_sport_id() == id)
{
it = m_game_list.erase(it);
this->on_erase(tmp); //customizable
delete tmp;
tmp = 0;
}
else
{
++it;
}
}
this->on_finish(); //customizable
}

Related

GoogleTest Mocking object method call fail

Hi so this is my first time utilizing googleTest Mocking. The general setup of the project is that coffeeMachine has an object coffeeStorage and coffeeStockService that it calls methods from coffeeMachine methods. I'm trying to create a mock test for the objects coffeeStorage and coffeeStockService but it's not recognizing the Expected Calls when I assign the mock objects to the coffeeMachine instance.
Trying to implement GoogleTest's mocking test framework but it's not recognizing the EXPECTED_CALL and also not letting me use mockedCoffeeStorage as a parameter to the method calls for mockedCoffeeStockService.. StockService Expected Call is because CoffeeMachine is also calling that but I passed in the coffeeStorage as a parameter. Is that possible for a mock object to cause a method that is using another mock object as the parameter and still expect the method to be called? Should I refactor and not include all the object references to the methods for CoffeeMachine since I already declare a CofeeStorage and CoffeeStockService object? Thank you so much
class coffeeMachine {
public:
coffeeStorage* CoffeeStorage;
coffeeStockService* CoffeeStockService;
bool coffeeServed = false;
coffeeMachine(coffeeStorage* CoffeeStorage, coffeeStockService* CoffeeStockService);
void start(string langIn);
void stop();
void descale();
void showSettings();
void hideSettings();
map<string, string> getSetting();
string message(coffeeStorage& CoffeeStorage);
void takeCoffee(coffeeStorage& CoffeeStorage);
void fillTank(coffeeStorage& CoffeeStorage, coffeeStockService& CoffeeStockService);
void fillBeans(coffeeStorage& CoffeeStorage, coffeeStockService& CoffeeStockService);
void emptyGrounds(coffeeStorage& CoffeeStorage, coffeeStockService& CoffeeStockService);
bool isDescalingNeeded();
class coffeeStorage {
private:
int waterStorage;
int beanStorage;
int trashStorage;
public:
//virtual ~coffeeStorage(){}
coffeeStorage();
virtual void takeCoffeeStorage();
virtual void setWaterStorage(int amount);
virtual void setBeansStorage(int amount);
virtual void emptyTrashStorage();
virtual int checkWater();
virtual int checkBeans();
virtual int checkTrashStorage();
};
class mockCoffeeStorage : public coffeeStorage {
private:
int waterStorage;
int beanStorage;
int trashStorage;
public:
MOCK_METHOD(void, takeCoffeeStorage, (), (override));
MOCK_METHOD(void, setWaterStorage, (int amount), (override));
MOCK_METHOD(void, setBeansStorage, (int amount), (override));
MOCK_METHOD(void, emptyTrashStorage, (), (override));
MOCK_METHOD(int, checkWater, (), (override));
MOCK_METHOD(int, checkBeans, (), (override));
MOCK_METHOD(int, checkTrashStorage, (), (override));
};
coffeeMachine::coffeeMachine(coffeeStorage* CoffeeStorage_, coffeeStockService* CoffeeStockService_){
waterHardness = "2";
grinder = "medium";
started = false;
coffeeServed = false;
settingsDisplayed = false;
CoffeeStorage = CoffeeStorage_;
CoffeeStockService = CoffeeStockService_;
message(*CoffeeStorage_);
descale();
fillTank(*CoffeeStorage_, *CoffeeStockService_);
fillBeans(*CoffeeStorage_, *CoffeeStockService_);
emptyGrounds(*CoffeeStorage_, *CoffeeStockService_);
}
string coffeeMachine::message(coffeeStorage& CoffeeStorage){
if(!started) return "";
if (settingsDisplayed) return i18n("settings");
if (CoffeeStorage.checkWater() <= 10) return i18n("tank");
if (CoffeeStorage.checkBeans() < 3) return i18n("beans");
if (CoffeeStorage.checkTrashStorage() >= 30) return i18n("grounds");
if (isDescalingNeeded()) return i18n("descale");
return i18n("ready");
}
void coffeeMachine::takeCoffee(coffeeStorage& CoffeeStorage){
if (CoffeeStorage.checkWater() == 0 || CoffeeStorage.checkBeans() == 0) {
coffeeServed = false;
} else {
coffeeServed = true;
CoffeeStorage.takeCoffeeStorage();
countdownToDescale -= 1;
}
}
void coffeeMachine::fillTank(coffeeStorage& CoffeeStorage, coffeeStockService& CoffeeStockService){
CoffeeStockService.restockWater(CoffeeStorage);
}
void coffeeMachine::fillBeans(coffeeStorage& CoffeeStorage, coffeeStockService& CoffeeStockService){
CoffeeStockService.restockBeans(CoffeeStorage);
}
void coffeeMachine::emptyGrounds(coffeeStorage& CoffeeStorage, coffeeStockService& CoffeeStockService){
CoffeeStockService.emptyTrash(CoffeeStorage);
}
TEST(MockObjTest, TestObjectCallsWithMock) {
mockCoffeeStorage mockedCoffeeStorage;
mockCoffeeStockService mockedCoffeeStockService;
EXPECT_CALL(mockedCoffeeStorage, checkWater())
.Times(AtLeast(1));
EXPECT_CALL(mockedCoffeeStorage, checkBeans())
.Times(AtLeast(1));
EXPECT_CALL(mockedCoffeeStorage, takeCoffeeStorage())
.Times(AtLeast(1));
coffeeMachine coffeeTest = coffeeMachine(&mockedCoffeeStorage, &mockedCoffeeStockService);
std::cout<< "Address of mockedCoffeeStorage: " << &mockedCoffeeStorage << "\n";
std::cout<< "Address of mockedCoffeeStockService: " << &mockedCoffeeStockService << "\n";
// EXPECT_CALL(mockedCoffeeStockService, restockWater(mockedCoffeeStorage))
// .Times(AtLeast(1));
// EXPECT_CALL(mockedCoffeeStockService, restockBeans(mockedCoffeeStorage))
// .Times(AtLeast(1));
// EXPECT_CALL(mockedCoffeeStockService, emptyTrash(mockedCoffeeStorage))
// .Times(AtLeast(1));
coffeeTest.start("en");
for(int i = 0; i < 10; i++)
{
if(coffeeTest.getBeansContent(mockedCoffeeStorage) < 5)
coffeeTest.fillBeans(mockedCoffeeStorage, mockedCoffeeStockService);
if(coffeeTest.getGroundsContent(mockedCoffeeStorage) > 20)
coffeeTest.emptyGrounds(mockedCoffeeStorage, mockedCoffeeStockService);
if(coffeeTest.getTankContent(mockedCoffeeStorage) < 15)
coffeeTest.fillTank(mockedCoffeeStorage, mockedCoffeeStockService);
coffeeTest.takeCoffee(mockedCoffeeStorage);
}
}
It's perfectly fine to set expect calls one mock with other mock as a parameter.
no need to pass the objects to each method - you can access them inside your functions because they're are members. This technique is called 'dependency injection'.
See this code (using GMock 1.8, so mock definition is slightly different):
// pure virt. interface, remember about virtual dtor
class coffeeStorage {
public:
virtual ~coffeeStorage() = default;
virtual void takeCoffeeStorage() = 0;
virtual void setWaterStorage(int amount) = 0;
virtual void setBeansStorage(int amount) = 0;
virtual void emptyTrashStorage() = 0;
virtual int checkWater() = 0;
virtual int checkBeans() = 0;
virtual int checkTrashStorage() = 0;
};
class coffeeStockService {
public:
virtual ~coffeeStockService() = default;
virtual void restockWater(coffeeStorage& storeage) = 0;
};
class coffeeMachine {
public:
coffeeMachine(coffeeStorage* CoffeeStorage, coffeeStockService* CoffeeStockService);
void fillTank() {
CoffeeStockService->restockWater(*CoffeeStorage);
}
void takeCoffee() {
if (CoffeeStorage->checkWater() == 0 || CoffeeStorage->checkBeans() == 0) {
coffeeServed = false;
}
else {
coffeeServed = true;
CoffeeStorage->takeCoffeeStorage();
}
}
bool isCoffeeServed() {
return coffeeServed;
}
private:
coffeeStorage* CoffeeStorage;
coffeeStockService* CoffeeStockService;
bool coffeeServed{false};
};
coffeeMachine::coffeeMachine(coffeeStorage* CoffeeStorage_, coffeeStockService* CoffeeStockService_)
: CoffeeStorage{CoffeeStorage_}
, CoffeeStockService{CoffeeStockService_} {}
class mockCoffeeStorage : public coffeeStorage {
public:
MOCK_METHOD0(takeCoffeeStorage, void());
MOCK_METHOD1(setWaterStorage, void(int amount));
MOCK_METHOD1(setBeansStorage, void(int amount));
MOCK_METHOD0(emptyTrashStorage, void());
MOCK_METHOD0(checkWater, int());
MOCK_METHOD0(checkBeans, int());
MOCK_METHOD0(checkTrashStorage, int());
};
class mockCoffeeStockService : public coffeeStockService {
public:
MOCK_METHOD1(restockWater, void(coffeeStorage& storeage));
};
struct MockObjTest : public testing::Test {
mockCoffeeStorage mockedCoffeeStorage;
mockCoffeeStockService mockedCoffeeStockService;
coffeeMachine coffeeTest = coffeeMachine(&mockedCoffeeStorage, &mockedCoffeeStockService);
};
TEST_F(MockObjTest, When_FillingTank_Then_RestocksWater) {
// assert
EXPECT_CALL(mockedCoffeeStockService, restockWater(testing::Ref(mockedCoffeeStorage)));
// act
coffeeTest.fillTank();
}
TEST_F(MockObjTest, Given_NoWater_When_TakingCoffee_Then_CoffeeNotServed) {
// arrange
EXPECT_CALL(mockedCoffeeStorage, checkWater()).WillOnce(testing::Return(0));
// act
coffeeTest.takeCoffee();
// assert
ASSERT_FALSE(coffeeTest.isCoffeeServed());
}
TEST_F(MockObjTest, Given_EnoughWaterWaterAndBeans_When_TakingCoffee_Then_takeCoffeeStorageAndCoffeeServed) {
// arrange
EXPECT_CALL(mockedCoffeeStorage, checkWater()).WillOnce(testing::Return(1));
EXPECT_CALL(mockedCoffeeStorage, checkBeans()).WillOnce(testing::Return(1));
EXPECT_CALL(mockedCoffeeStorage, takeCoffeeStorage()); // this is more of the 'assert' part, but it cannot be moved to the end of the test
// act
coffeeTest.takeCoffee();
// assert
ASSERT_TRUE(coffeeTest.isCoffeeServed());
}
This is trimmed and simplified version of your code, but this should get you running. Always try to start with some v. easy, minimal test and build from this adding more complexity. If the tests becomes too complex/complicated, it is probably time to separate some parts of your code to the new class and test this class in separation.

Segmentation fault when trying to clean object in Gtest

So, this is my test. But it has segmentation fault on the last line: m->service-> clean. And if I don't use this function, I have memory leaks. Is there any alternative?
class ServiceTest: public ::testing::Test
{
protected:
virtual void SetUp()
{
m_service = new conn::tsm::Service();
}
virtual void TearDown()
{
delete m_service;
m_service = 0;
}
// Tested Object:
conn::Service *m_service;
};
TEST_F(ServiceTest, CatchChildDelete)
{
conn::IObject_mock *testParam = new conn::IObject_mock();
m_service->setId(0x01);
EXPECT_CALL(*testParam, getId()).WillRepeatedly(::testing::Return(0x01));
EXPECT_TRUE(m_service->addObject(testParam));
EXPECT_CALL(*testParam, die()).WillOnce(::testing::Throw(std::exception()));
m_service->clean();
}
And this is the implementation of clean():
void Service::clean() throw()
{
try
{
std::vector<IObject *>::iterator it = m_objectTable.end();
for( it = m_objectTable.begin(); it != m_objectTable.end();++it )
{
delete (*it);
}
/* clear cache */
m_objectMap.clear();
m_objectTable.clear();
}
catch(...)
{
}
}

What is a good way to make a polymorph Task interface in c++?

What is a good way to make a polymorph Task interface?
I want to design an interface for a processing library, which takes different data objects.
All data objects inherit from a IDataObject class.
The objects should be passed to the task throug a setInput(IDataObject* input) function.
I want to be able to define which kind of data object is needed. Maybe through a function setRequieredInput(DataObjectBase* input).
It should be possible to find Tasks which are able to process a data object maybe like this vector<Task*> getTasks(DataObjectBase* input). Like a Microkernel (Dependency Container)?
All suggestions are welcome.
I listed an first shoot below:
class IDataObject {
// Visitor style implementation
virtual void multiDispatch(Task* task) = 0;
}
class ISingleAccessDataObject : IDataObject {
// Visitor style implementation
// would this work orcan't I use the definition derived
// virtual function for the "interface" and class?
// If I'm right this is the diamond problem (inheriting the same
// function twice).
virtual void multiDispatch(Task* task) = 0;
double getData(int i) = 0;
}
class DataObjectBase : IDataObject {
// Visitor style implementation
virtual void multiDispatch(Task* task) {
task->execute(this);
}
// ...
}
class DataObjectBase {
// Visitor style implementation
virtual void multiDispatch(Task* task) {
task->execute(this);
}
// ...
}
class DerivedDataObject : DataObjectBase, ISingleAccessDataObject {
// Visitor style style Implementation
virtual void multiDispatch(Task* task) {
task->execute(this);
}
// ...
}
class Task {
void setInput(DataObjectBase* input) {
if (checkCanHandle(input) {
m_inputs.push_back(input);
}
}
void execute() {
for (int i = 0; i < m_Inputs.size(); i++) {
IDataObject* dataObject = m_Inputs.at(i);
if (dataObject == NULL) {
continue;
}
//-----------------------
// Visitor style implementation
dataObject.multiDispatch(this);
//-----------------------
// or
//-----------------------
if (Derived1DataObject* derived1DataObject = dynamic_cast<Derived1DataObject>(dataObject )) {
// ...
} else if (ISingleAccessDataObject* singleAccessDataObject = dynamic_cast<SingleAccessDataObject>(dataObject)) {
// ...
} else { //Log error }
//-----------------------
}
}
// Visitor style implementation
//-----------------------
// This would require to know all DataObjects on defining the
// Task "Interface". What is not really what I want.
void execute(Derived1DataObject* input) {
// ..
}
void execute(Derived2DataObject* input) {
// ..
}
void execute(ISingleIndexAccessDataObject* input) {
// ..
}
//-----------------------
bool checkCanHandle(DataObjectBase* input) {
for (int i = 0; i < m_HandleDataObjects.size(); i++) {
// Question: Is there a way to let this be true if
// m_HandleDataObjects.at(i) is a super class of input?
// Question: Is there a way to allow only save something like
// the typeid. Maybe name, but I'm not sure if name is the best
// option.
if (typeid(m_HandleDataObjects.at(i)) == typeid(input)) {
return true;
}
}
}
vector<DataObjectBase*> m_HandleDataObjects;
vector<DataObjectBase*> m_Inputs;
}
class TaskRegister {
vector<Task*> getTasks(IDataObject* input) {
vector<Task*> ret;
for (int i = 0; i < m_Tasks.size(); i++) {
// Question: Is there a better way using a HashMap or something else
if (m_Tasks.at(i).checkCanHandle(input)) {
ret.push_back(m_Tasks.at(i));
}
}
return ret;
}
vector<Task*> m_Tasks;
}

Why this Node List doesen't work correct?

Why, although I have add 4 GameObjects, in the GameLoop the Console give only one times "GameObject Update" and "GameObject Render" out ?
And another Qustion, how I can made a Self Destroy Function for the GameObjects?
And the last Question, whats the best methode, that a GameObject can communicate with other game objects in the list?
#include <iostream>
using namespace std;
class GameObject
{
public:
GameObject *nextGameObject;
GameObject()
{
cout<<"GameObject Constructor!\n";
nextGameObject = nullptr;
}
~GameObject()
{
cout<<"GameObject Destructor\n";
if(nextGameObject != nullptr)
{
delete nextGameObject;
}
}
virtual void Update()
{
cout<<"GameObject Update!\n";
}
virtual void Render()
{
cout<<"GameObject Render!\n";
}
};
class GameObjectManager
{
private:
GameObject *firstGameObject;
public:
GameObjectManager()
{
firstGameObject = nullptr;
}
~GameObjectManager()
{
if(firstGameObject != nullptr)
{
delete firstGameObject;
}
}
void Update()
{
if(firstGameObject != nullptr)
{
GameObject *helpGameObject = firstGameObject;
while(helpGameObject != nullptr)
{
helpGameObject->Update();
helpGameObject = helpGameObject->nextGameObject;
}
}
}
void Render()
{
if(firstGameObject != nullptr)
{
GameObject *helpGameObject = firstGameObject;
while(helpGameObject != nullptr)
{
helpGameObject->Render();
helpGameObject = helpGameObject->nextGameObject;
}
}
}
void Add(GameObject *newGameObject)
{
if(firstGameObject == nullptr)
{
firstGameObject = newGameObject;
}
else
{
GameObject *helpGameObject = firstGameObject;
while(helpGameObject != nullptr)
{
helpGameObject = helpGameObject->nextGameObject;
}
helpGameObject = newGameObject;
}
}
};
int main()
{
GameObjectManager gom;
bool run = true;
gom.Add(new GameObject);
gom.Add(new GameObject);
gom.Add(new GameObject);
gom.Add(new GameObject);
while(run)
{
cout<<"GameLoop Start\n";
gom.Update();
gom.Render();
cout<<"GameLoop End\n";
cin.get();
}
return 0;
}
This is a horrible solution for a linked list, but I'll answer your question. The fault is in Add(). Here, you just modify the local variable helpGameObject. Instead you should stop at the object that has no successor and modify that objects nextGameObject.
The problem is in your Add function.
the follwing line:
helpGameObject = newGameObject;
doesn't actually change the value pointed to by helpGameObject, rather it changes the pointer itself.
I think the best solution is to change it to the following
GameObject *helpGameObject = firstGameObject;
while(helpGameObject->nextGameObject != nullptr)
{
helpGameObject = helpGameObject->nextGameObject;
}
helpGameObject->nextGameObject = newGameObject;

Where to plug in the factory method in the abstract factory pattern?

// Abstract factory class
class pizzaStore
{
public:
vector <string> toppingsType;
virtual void bakePizza (){}
virtual void preparePizza ()
{
for (int i = 0; i < toppingsType.size (); i++)
{
addTopping (toppingsType[i]);
}
}
virtual void cutPizza (){}
virtual void boxPizza (){}
};
class xPizzaStore : public pizzaStore
{
xPizzaStore ()
{
toppingsType = "1";
sauceType = "2";
cheesetype = "3";
}
void orderPizza ()
{
bakePizza ();
preparePizza ();
// xPizzaStore doesn't cut the pizza.
boxPizza ();
}
};
// Factory method for creating stores
pizzaStore * whichStore (string storeName)
{
pizzaStore obj = NULL;
if (storeName == "x")
{
obj = new xPizzaStore ();
}
else if (storeName == "y")
{
obj = new yPizzaStore ();
}
else if (storeName == "z")
{
obj = new zPizzaStore ();
}
return obj;
}
// Factory method for creating pizzas
pizzaStore * whichPizza (string pizzaName)
{
pizzaName obj = NULL;
if (pizzaBaseType == "x")
{
obj = new xPizzaName ();
}
else if (pizzaBaseType == "y")
{
obj = new yPizzaName ();
}
else if (pizzaBaseType == "z")
{
obj = new zPizzaName ();
}
return obj;
}
There can be different types of stores as well as pizzas.
In which class should these two factory methods be included and why?
Does it make sense to include them in the pizzaStore class itself?
Does it make sense to include them in the pizzaStore class itself?
Yes, it should be perfectly fine to put those method in class pizzaStore as static methods. Generally I consider, putting such factory method in a class based on its return type, and pizzaStore is a good candidate for it.