Úprava kódu – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Úprava kódu – C / C++ – Fórum – Programujte.comÚprava kódu – C / C++ – Fórum – Programujte.com

 

vesi
~ Anonymní uživatel
7 příspěvků
18. 5. 2015   #1
-
0
-

Ahoj,

předem se omlouvám za triviální dotaz, ale neprogramuju v C++, ale v C# takže je to pro mě nepřekonatelný problém :) 

Měl jsem funkci

#ifndef ABSTRACT_LOGGER_H
#define ABSTRACT_LOGGER_H

#include <string>

namespace Palo {
namespace SpreadsheetFuncs {
class AbstractLogger {
public:
    enum Type {
        LOG_ERROR, LOG_WARNING, LOG_INFO
    };

    virtual void log(Type t, const std::string msg) throw () = 0;
};
}
}
#endif

kterou volala následující funkce 

#ifndef XLL_CELL_LOGGER_H
#define XLL_CELL_LOGGER_H


#include <fstream>

#include <PaloSpreadsheetFuncs/AbstractLogger.h>

namespace Palo {
	namespace XLL {
		class XLLCellLogger : public Palo::SpreadsheetFuncs::AbstractLogger {
		public:
			XLLCellLogger();
			~XLLCellLogger();

			static XLLCellLogger& getInstance() {
				static XLLCellLogger pl;
				return pl;
			}

			void log( Type t, std::string msg, bool force_logging ) throw();
			void log( Type t, std::string msg ) throw() {
				log(t, msg, false);
			};

		private:
			std::ofstream m_log;
		};
	}
}
#endif

bohužel se první funkce změnil string 

#ifndef ABSTRACT_LOGGER_H
#define ABSTRACT_LOGGER_H

#include <string>

namespace Palo {
namespace SpreadsheetFuncs {
class AbstractLogger {
public:
	enum Type {
		LOG_ERROR, LOG_WARNING, LOG_INFO
	};

	virtual void log(Type t, const std::string &msg) throw () = 0;
};
}
}
#endif

zkoušel jsem tedy kód upravit následně 

#ifndef XLL_CELL_LOGGER_H
#define XLL_CELL_LOGGER_H


#include <fstream>

#include <PaloSpreadsheetFuncs/AbstractLogger.h>

namespace Palo {
	namespace XLL {
		class XLLCellLogger : public Palo::SpreadsheetFuncs::AbstractLogger {
		public:
			XLLCellLogger();
			~XLLCellLogger();

			static XLLCellLogger& getInstance() {
				static XLLCellLogger* pl;
				return *pl;
			}

			void log( Type t, std::string msg, bool force_logging ) throw();
			void log( Type t, std::string msg ) throw() {
				log(t, msg, false);
			};

		private:
			std::ofstream m_log;
		};
	}
}
#endif

Což sice projde kompilací, ale v reálu to pak nefunguje. Mohl by mi někdo poradit jak správně kód upravit? Díky.

Nahlásit jako SPAM
IP: 213.220.252.–
ondrej39+1
Věrný člen
18. 5. 2015   #2
-
0
-

#1 vesi
A proč měníš getInstance metodu, když jsi upravoval pure virtual funkci třídy AbstractLogger? Přidej si referenci i do funkce log, kterou implementuješ z abstraktní třídy.

void log( Type t, std::string& msg ) throw() {
				log(t, msg, false);
			};

Co se metody getInstance týče, na co si vytváříš statickej ukazatel XLLCellLogger? Nechceš náhodou vytvořit statický objekt? Využij move sémantiky, kterou C++ v nových verzí nabízí. Deklaraci ukazatele a dereferenci pryč.

Každopádně ten ofstream ti tam, myslím si, stejně bude dělat docela bordel, protože by se měl přenést (zkopírovat), což bohužel nejde. Asi bych zvolil jiný typ proměnné pro uchování logu, třeba standardní std::string.

Nahlásit jako SPAM
IP: 213.226.234.–
Inject all the dependencies!
vesi
~ Anonymní uživatel
7 příspěvků
19. 5. 2015   #3
-
0
-

#2 ondrej39
Díky za odpověď. Já bohužel nemůžu měnit kód v AbstractLogger, protože je v jiné knihovně, jehož kód já nemám pod "kontrolou". Takže potřebuji upravit XLLCellLogger, tak aby fungoval se změnou const std::string &msg. Jak jsem psal nahoře, programuju v C#, ale C++ je pro mě španělská vesnice... :(

Nahlásit jako SPAM
IP: 94.113.246.–
ondrej39+1
Věrný člen
19. 5. 2015   #4
-
0
-

#3 vesi
Jde o to, že když definuješ virtual / pure virtual metodu z rodiče, tak je třeba, aby ta tvá definice měla stejný přepis (stejnou deklaraci) jako funkce rodičovská.

Původní metoda používala předávání stringu hodnotou, a na to jsi měl tu svou funkci log, oni to změnili na předávání stringu pomocí konstantní reference a kvůli tomu musíš upravit tu svou funkci v XLLCellLogger, aby ten přepis souhlasil...

Takže prostě zkopíruješ deklaraci dané metody, kterou implementuješ. Zmeň si v té své třídě XLLCellLogger metodu na 

void log( Type t, std::string& msg ) throw()

To je jako když v C# děláš 

public override bool Equals(object o)

Ačkoliv toto většinou implementuješ pro konkrétní objekt a chceš proovnávat jen dva objekty stejného typu, tak musíš mít v deklaraci jako parametr object a ne třídu, pro niž danou metodu děláš, a přetypování object si udělat až uvnitř té funkce, protože rodičovská metoda Equals má v parametru právě ten object, a to musí souhlasit.

Nahlásit jako SPAM
IP: 195.113.207.–
Inject all the dependencies!
KIIV
~ Moderátor
+43
God of flame
19. 5. 2015   #5
-
0
-

Divim se, ze slo zkompilovat i tu prvni verzi -  log je tam ciste virtualni a MUSI se definovat v potomku, aby to vubec mohlo kdy jit zkompilovat.

A v potomku nemas ani jednu metodu, ktera by to mela teoreticky predefinovat. Musi tam byt uplne presne to same (akorat bez  = 0; na konci), jako v te AbstractLogger.

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
vitamin
~ Anonymní uživatel
1092 příspěvků
19. 5. 2015   #6
-
0
-

#3 vesi

Ak používaš c++11/c++14 tak si môžeš použiť override specifier. Funguje ako v C# len sa dava az za funkciu:

Nahlásit jako SPAM
IP: 195.28.77.–
vitamin
~ Anonymní uživatel
1092 příspěvků
19. 5. 2015   #7
-
0
-

   

void log( Type t, std::string& msg ) noexcept override{}	//kompilator ti vypise chybu lebo ti tam chyba const
Nahlásit jako SPAM
IP: 195.28.77.–
vesi
~ Anonymní uživatel
7 příspěvků
19. 5. 2015   #8
-
0
-

Díky za komentáře.

Upravil jsem kód následovně 

namespace Palo {
	namespace XLL {
		class XLLCellLogger : public Palo::SpreadsheetFuncs::AbstractLogger {
		public:
			XLLCellLogger();
			~XLLCellLogger();

			static XLLCellLogger& getInstance() {
				static XLLCellLogger pl;
				return pl;
			}
			void log( Type t, std::string& msg ) throw();
			void log( Type t, std::string& msg, bool force_logging ) throw();

		private:
			std::ofstream m_log;
		};
	}
}

protože potřebuji i variantu s 3 parametrem, která se používá dál v kódu. 

Ale bohužel mě to vyhází nasledující chyby

Error	1	error C2259: 'Palo::XLL::XLLCellLogger' : cannot instantiate abstract class	d:\develop\xladdin\libraries514\paloxll\XLLCellLogger.h	52
Error	2	error C2664: 'void Palo::XLL::XLLCellLogger::log(Palo::SpreadsheetFuncs::AbstractLogger::Type,std::string &,bool) throw()' : cannot convert parameter 2 from 'const char *' to 'std::string &'	D:\Develop\XlAddin\libraries514\PaloXLL\c2c_plus_plus.cpp	40
Error	3	error C2259: 'Palo::XLL::XLLCellLogger' : cannot instantiate abstract class	d:\develop\xladdin\libraries514\paloxll\XLLCellLogger.h	52
Error	4	error C2259: 'Palo::XLL::XLLCellLogger' : cannot instantiate abstract class	d:\develop\xladdin\libraries514\paloxll\XLLCellLogger.h	52
Error	5	error C2511: 'void Palo::XLL::XLLCellLogger::log(Palo::SpreadsheetFuncs::AbstractLogger::Type,std::string,bool) throw()' : overloaded member function not found in 'Palo::XLL::XLLCellLogger'	D:\Develop\XlAddin\libraries514\PaloXLL\XLLCellLogger.cpp	68
Error	6	error C2259: 'Palo::XLL::XLLCellLogger' : cannot instantiate abstract class	d:\develop\xladdin\libraries514\paloxll\XLLCellLogger.h	52
Error	7	error C2664: 'void Palo::XLL::XLLCellLogger::log(Palo::SpreadsheetFuncs::AbstractLogger::Type,std::string &) throw()' : cannot convert parameter 2 from 'const char [57]' to 'std::string &'	D:\Develop\XlAddin\libraries514\PaloXLL\SpreadsheetFuncsWrapper.cpp	128
Nahlásit jako SPAM
IP: 94.113.246.–
KIIV
~ Moderátor
+43
God of flame
19. 5. 2015   #9
-
0
-

to je zase nevyhoda pouziti reference na string - neda se z C style retezce uz automaticky vyrobit std::string

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
vesi
~ Anonymní uživatel
7 příspěvků
19. 5. 2015   #10
-
0
-

Takže jestli to chápu dobře, tak jediná možnost pro mě je, vrátit zpět v AbstractLogger parametr const std::string &msg na const std::string msg, jak to bylo původně. To sice funguje, ale chtěl jsem se tomu vyhnout, protože AbstractLogger je součástí open source řešení, které je aktualizováno a já to budu muset při každé aktualizaci upravovat ve zdrojovém kódu...

Nahlásit jako SPAM
IP: 94.113.246.–
ondrej39+1
Věrný člen
19. 5. 2015   #11
-
0
-

#10 vesi
Pod čím kompiluješ? Ve VS2013 mi to s tímto zápisem C2664 vůbec nehází. (Oddělej referenci u funkce log se třemi parametry.)

#ifndef ABSTRACT_LOGGER_H
#define ABSTRACT_LOGGER_H

#include <string>

namespace Palo {
	namespace SpreadsheetFuncs {
		class AbstractLogger {
		public:
			enum Type {
				LOG_ERROR, LOG_WARNING, LOG_INFO
			};

			virtual void log(Type t, const std::string& msg) throw () = 0;
		};
	}
}
#endif

////////////////////////////////////

#ifndef XLL_CELL_LOGGER_H
#define XLL_CELL_LOGGER_H

#include <fstream>

//includuji to jinak, to si u sebe změň
#include "AbstractLogger.h"

namespace Palo {
	namespace XLL {
		class XLLCellLogger : public Palo::SpreadsheetFuncs::AbstractLogger {
		public:
			XLLCellLogger();
			~XLLCellLogger();

			static XLLCellLogger& getInstance() {
				static XLLCellLogger pl;
				return pl;
			}

			void log(Type t, std::string msg, bool force_logging) throw();
			virtual void log(Type t, const std::string& msg) throw() {
				log(t, msg, false);
			};

		private:
			std::ofstream m_log;
		};
	}
}
#endif

Nicméně to řve kvůli volání smazaného copy konstruktoru třídy std::ofstream (jak jsem již psal ve 2. příspěvku). Použij na logování něco jiného.

Nahlásit jako SPAM
IP: 195.113.207.–
Inject all the dependencies!
vesi0
Duch
19. 5. 2015   #12
-
0
-

Kompiluju to pod VS2010 SP1. Upravil jsem to podle tebe, ale pořád mi to řve na řádku 

static XLLCellLogger pl; 

Error	2	error C2259: 'Palo::XLL::XLLCellLogger' : cannot instantiate abstract class	d:\develop\xladdin\libraries514\paloxll\XLLCellLogger.h	52

a pak na řádku 

XLLCellLogger::getInstance().log( AbstractLogger::LOG_WARNING, "Unexpected exception caught! (This should never happen)." ); 

Error	5	error C2664: 'void Palo::XLL::XLLCellLogger::log(Palo::SpreadsheetFuncs::AbstractLogger::Type,std::string &) throw()' : cannot convert parameter 2 from 'std::string *' to 'std::string &'	D:\Develop\XlAddin\libraries514\PaloXLL\SpreadsheetFuncsWrapper.cpp	129
	6	IntelliSense: no instance of overloaded function "Palo::XLL::XLLCellLogger::log" matches the argument list	d:\develop\xladdin\libraries514\paloxll\spreadsheetfuncswrapper.cpp	128

Tady mě je jasné, že je problém s tím, že se předává string nikoliv reference na string, ale nevím jak to přepsat.

Ještě jednou se omlouvám, je mi jasné, že to co tu řeším jsou asi základy, ale já C++ naposledy viděl asi před 15 lety na vejšce, tak díky za trpělivost :)

Nahlásit jako SPAM
IP: 94.113.246.–
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, 65 hostů

Podobná vlákna

Uprava kodu — založil david

Úprava XML kodu — založil MaxDJs

Úprava PHP kódu — založil Gabriel

Úprava vstupního kódu — založil Draffix

Uprava kodu coocie — založil Vlček

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ý