C++ template a podmínky – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

C++ template a podmínky – C / C++ – Fórum – Programujte.comC++ template a podmínky – C / C++ – Fórum – Programujte.com

 

Jan
~ Anonymní uživatel
187 příspěvků
6. 12. 2012   #1
-
0
-

Dobrý den,
řeším už třetí den problém týkající se předání několika objektů funkci, která je zpracuje dál. Problém jsem se rozhodl řešit pomocí template, ale vzhledem k faktu, že jsem tento aspekt jazyka C++ do dnes nikdy nepoužil, někde zřejmě dělám chybu.

Princip předpokládané funkčnosti:
Ve funkci main vytvořím instanci třídy ContextManager, která má za úkol spravovat reference na ostatní důležité objekty systému, resp. programu(SystemManager, ConfigManager, VideoManager, ...). Po té se zavolá funkce setContext, která je řešená pomocí template a má za úkol přijmout některý z výše uvedených systémových objektů a uložit odkaz, nebo nějakou vazbu na něj v ContextManager-u pro další použití. Každý z ostatních systémových objektů (SystemManager, ConfigManager, VideoManager, ...) očekává ve svém konstruktoru ukazatel na instanci ContextManager-u, aby měl přístup k veškerým objektům, které budou uloženy v ContextManageru.
 

Problém:
Ve třídě ContextManager, resp. jeho fci setContext, která je (nebo by podle mého plánu být měla :)) generická (template), přijmu systémový objekt a podle vlastnosti object_name tohoto objektu větvím ukládání objektu do předpřipraveného pointeru, pro něj určeného. Fce v základu funguje jak má, ale ve chvíli kdy odkomentuji, resp. přidám do každé if větve řádek
this->object__system_manager = &object_reference;
tak kompilátor (VS2010) začne křičet, že to nepůjde...
 

Takže tedy prosím o radu někoho zkušenějšího, než jsem já. Nevím jak kód přepsat, aby vše fungovalo, nebo jakým jiným způsobem danou funkčnost řešit. Snad mi někdo ušetříte pár vrásek, jsem z toho už celkem zoufalý... :)

Díky za Vaše odpovědi

Výpis kompilátoru:

------ Build started: Project: client (Visual Studio 2010), Configuration: Debug Win32 ------
1>  main.cpp
1>d:\programing\cpp11\project_game_2\client\contextmanager.h(70): error C2440: '=' : cannot convert from 'SystemManager *' to 'ConfigManager *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          d:\programing\cpp11\project_game_2\client\main.cpp(59) : see reference to function template instantiation 'void ContextManager::setContext<SystemManager>(generic_system_object)' being compiled
1>          with
1>          [
1>              generic_system_object=SystemManager
1>          ]
1>d:\programing\cpp11\project_game_2\client\contextmanager.h(78): error C2440: '=' : cannot convert from 'SystemManager *' to 'VideoManager *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\programing\cpp11\project_game_2\client\contextmanager.h(62): error C2440: '=' : cannot convert from 'ConfigManager *' to 'SystemManager *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          d:\programing\cpp11\project_game_2\client\main.cpp(63) : see reference to function template instantiation 'void ContextManager::setContext<ConfigManager>(generic_system_object)' being compiled
1>          with
1>          [
1>              generic_system_object=ConfigManager
1>          ]
1>d:\programing\cpp11\project_game_2\client\contextmanager.h(78): error C2440: '=' : cannot convert from 'ConfigManager *' to 'VideoManager *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\programing\cpp11\project_game_2\client\contextmanager.h(62): error C2440: '=' : cannot convert from 'VideoManager *' to 'SystemManager *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          d:\programing\cpp11\project_game_2\client\main.cpp(64) : see reference to function template instantiation 'void ContextManager::setContext<VideoManager>(generic_system_object)' being compiled
1>          with
1>          [
1>              generic_system_object=VideoManager
1>          ]
1>d:\programing\cpp11\project_game_2\client\contextmanager.h(70): error C2440: '=' : cannot convert from 'VideoManager *' to 'ConfigManager *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Kód je zde zjednodušený, pouze na věci týkající se problému
 

fce main

ContextManager main__context_manager = ContextManager();

main__context_manager.setContext<SystemManager>(SystemManager(&main__context_manager));

main__context_manager.setContext<ConfigManager>(ConfigManager(&main__context_manager));

main__context_manager.setContext<VideoManager>(VideoManager(&main__context_manager));


ContextManager.h

#ifndef __CONTEXT_MANAGER_H__
#define __CONTEXT_MANAGER_H__

#include <iostream>

#include "SystemManager.h"


class SystemManager;
class ConfigManager;
class VideoManager;

class ContextManager{
	public:
		ContextManager();
		
		template <class generic_system_object> void setContext(generic_system_object object_reference);

		SystemManager *object__system_manager;
		ConfigManager *object__config_manager;
		VideoManager *object__video_manager;
};


ContextManager::ContextManager(){
	
}

template <class generic_system_object> void ContextManager::setContext(generic_system_object object_reference){
	if(object_reference.object_name == "SystemManager"){
		this->object__system_manager = &object_reference;
	}
	if(object_reference.object_name == "ConfigManager"){
		this->object__config_manager = &object_reference;
	}
	if(object_reference.object_name == "VideoManager"){
		this->object__video_manager = &object_reference;
	}
}


#endif


takhle vypadá konstruktor všech systémových objektů (příklad):

SystemManager::SystemManager(ContextManager *local__context_manager){
  object_name = "SystemManager";}
Nahlásit jako SPAM
IP: 194.228.11.–
crazy
~ Moderátor
+10
Grafoman
6. 12. 2012   #2
-
0
-

#1 Jan
nevím proč v tomto případě používat template. Využij dědičnosti vytvoř nadtřídu Manager a předávej pointer na Manager.

Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
Jan
~ Anonymní uživatel
187 příspěvků
6. 12. 2012   #3
-
0
-

#2 crazy
Můžeš prosím rozvést, jak to myslíš?

Nahlásit jako SPAM
IP: 194.228.11.–
crazy
~ Moderátor
+10
Grafoman
6. 12. 2012   #4
-
0
-

#1 Jan
 

class Manager;

class SystemManager : public Manager 
{
}

class ContextManager : public Manager
{
	Manager *systemManager;

	void setContext(Manager * m)
	{
		systemManager = m;
	}
}

ContextManager cm;
cm.setContext(new SystemManager());

nejak takto, snad je to z toho videt

Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
Jan
~ Anonymní uživatel
187 příspěvků
6. 12. 2012   #5
-
0
-

#4 crazy
To už jsem zkoušel, byla to v podstatě druhá věc, která mě napadla. Problém je, že se pak v main-u nedostanu k metodám objektů, které jsou uložen v ContextManageru.

Např.:
main__context_manager.object__system_manager->printColoredText("Main program started", 12);
V tomhle případě například k základní metodě SystemManageru, tedy metodě printColoredText...

Předpokládám, že z důvodu, že ten objekt je v tu chvíli typu BaseSystemObject (můj předek sysémových objektů), resp. v tvém příkladě typu Manager. Asi pak nejsou vidět metody, které např. ten SystemManager má. 

Možná k tomu přistupuji špatně, něco jsem opomenul, nebo uvažoval špatně, nevím.

Nahlásit jako SPAM
IP: 194.228.11.–
vitamin+8
Grafoman
6. 12. 2012   #6
-
0
-

#5 Jan
Mozes pouzit dynamic_cast na zystenie typu pocas behu programu (ale skor to vyzera na divny navrh programu)

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Jan
~ Anonymní uživatel
187 příspěvků
6. 12. 2012   #7
-
0
-

#6 vitamin
Jop, díky. :)  Už jsem se mezi tím o dynamic_cast dočetl a zkouším to pomocí něj. Uvidíme, jak to půjde.

K tomu špatnému návrhu programu - je to možné. Hezkých pár let jsem pořádně neprogramoval, teď se k tomu vracím a rovnou jsem začal s C++. 
Když už jsi zmínil návrh programu, mám k tomu taky dotaz. Jak se v OOP řeší komunikace mezi objekty? Když jeden objekt chce zavolat metodu druhého, je potřeba mít nějakou referenci na ten druhý objekt, tak se snažím udělat správce těchto objektů. Odkaz na něj dostane každý objekt a z něj si vytáhne odkazy na ostatní, které bude potřebovat pro práci. Uvažuju nad tím až tak špatně?

Nahlásit jako SPAM
IP: 194.228.11.–
zlz
~ Anonymní uživatel
634 příspěvků
6. 12. 2012   #8
-
0
-

Hele, máš v tom chaos, udělej si tam 3 set/gettery, nebo udělej ty členy public. Aspoň to bude fungovat a dělat to pořádně se naučíš časem. Bez urážky, někdy je to celkem věda.

Nahlásit jako SPAM
IP: 78.156.159.–
Jan
~ Anonymní uživatel
187 příspěvků
6. 12. 2012   #9
-
0
-

#8 zlz
Díky za reakci, ale tohle mě napadlo taky. Udělat to stupid-friendly (hromada set/get metod) není až tak těžké, ale snažím se to vyřešit trochu inteligentněji. Vzhledem k plánu, že to bude ve výsledku poněkud komplikovanější program, tak tam nechci mít desítky přetížených metod. Nepřijde mi to jako nejlepší řešení, i přes to, že je nejjednodušší.

PS.: To naučení se časem se právě teď snažím realizovat. ;)

Nahlásit jako SPAM
IP: 194.228.11.–
vitamin+8
Grafoman
6. 12. 2012   #10
-
0
-

#9 Jan
nestaci ti daco taketo?

struct ContextManager{
	SystemManager *system_manager = nullptr;
	ConfigManager *config_manager = nullptr;
	VideoManager *video_manager = nullptr;
};
Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Jan
~ Anonymní uživatel
187 příspěvků
6. 12. 2012   #11
-
0
-

Tak jsem to nakonec vyřešil přes ten dynamic_cast...

Všechny objekty dědí z abstraktní třídy BaseSystemObject, do té metody v ContextManager-u je vstupem pointer na BaseSystemObject a ten po přijetí přetypuji na objekt podle potřeby.

void ContextManager::setContext(BaseSystemObject *object_reference){
	if(object_reference->object_name == "SystemManager"){
		object__system_manager = dynamic_cast<SystemManager*>(object_reference);
	}
	if(object_reference->object_name == "ConfigManager"){
		object__config_manager = dynamic_cast<ConfigManager*>(object_reference);
	}
	if(object_reference->object_name == "VideoManager"){
		object__video_manager = dynamic_cast<VideoManager*>(object_reference);
	}
}

Díky za pomoc.

Nahlásit jako SPAM
IP: 194.228.11.–
vitamin+8
Grafoman
6. 12. 2012   #12
-
0
-

#11 Jan
V tomto pripade by ti zrejme stacil reinterpret_cast. Mozno by bolo lepsie pouzit na identyfikaciu typov integer(enum je integer) a nie string: 

enum class Manager{System, Config, Video};

void ContextManager::setContext(BaseSystemObject *object_reference){
	switch(object_reference->object_id){//object_id bude mat typ Manager

		case Manager::System:
			object__system_manager = reinterpret_cast<SystemManager*>(object_reference);
			break;
		case Manager::Config:
			object__config_manager = reinterpret_cast<ConfigManager*>(object_reference);
			break;
		case Manager::Video:
			object__video_manager = reinterpret_cast<VideoManager*>(object_reference);
			break;
		}
}

edit: Ak pouzivas virtualne triedy, tak kazdy objekt obsahuje pointer na tabulku virtualnych metod. Hodnota tochto pointra dostatocne identifikuje typ objektu (pomocou dynamic_cast<>() alebo typeid()). Takze v tvojom pripade je zbytocne mat premennu 'object_name'.  

Tvoj kod by sa dal upravyt na:

void ContextManager::setContext(BaseSystemObject *object_reference){
	if(dynamic_cast<SystemManager*>(object_reference)){
		object__system_manager = reinterpret_cast<SystemManager*>(object_reference);
	}
	//alebo:
	else if(typeid(ConfigManager) == typeid(*object_reference)){
		object__config_manager = reinterpret_cast<ConfigManager*>(object_reference);
	}
	//...
}
Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 17 hostů

Podobná vlákna

Template — založil MiCizek

Template — založil janek

Web template — založil Anonymní uživatel

Template header — založil TauWich

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý