• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[C++] undefined reference to namespace::constructor .

Object Storage Arubacloud
0 głosów
718 wizyt
pytanie zadane 27 kwietnia 2018 w C i C++ przez Hiskiel Pasjonat (22,830 p.)
edycja 27 kwietnia 2018 przez Hiskiel

Witam,

 

chciałem sobie napisać pewien program. Dodałem sobie dwa pliki (*.cpp i *.h). W pliku nagłówkowym jest deklaracja klasy, w namespace. Kiedy próbuję wywołać konstruktor dostaję błąd:

D:\AppData\Tmp\cczno6HG.o:main.cpp:(.text+0x171): undefined reference to `ArgP::
ArgumentParser::ArgumentParser(int, char**)'
collect2.exe: error: ld returned 1 exit status

(tak swoją drogą nie wiem dlaczego ta ścieżka to D:\AppData\...)

Tutaj kod:

main.cpp

#include <iostream>
#include <fstream>
#include <windows.h>
#include "ArgParser.h"

void color(int color){
	static HANDLE ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(ConsoleHandle, color);
}

bool IsExist(const char* Path){
	static std::ifstream stream(Path);
	if(!stream.is_open()) return false;
	return true;
}

int main(int argc, char* argv[]){
	ArgP::ArgumentParser ArgParser(argc, argv);
}

 ArgParser.h:

#include <string>
#include <vector>
#include <string.h>

namespace ArgP{
	std::string EMPTY_ERR = "0-EmptySentenceError-0";
	std::string OFB_ERR = "0-OutOfBoundError-0";
	class ArgumentParser{
	public:
		ArgumentParser(int ArgCount, char* ArgVal[]);
		~ArgumentParser() = default;
		std::string operator[](int index);
	private:
		int ArgCount = 0;
		int max = 0;
		std::vector<std::string> ArgValues;
	};
}

ArgParser.cpp:

#include "ArgParser.h"

ArgP::ArgumentParser::ArgumentParser(int ArgCount, char* ArgVal[]){
	this->max = ArgCount;

	ArgValues.reserve(ArgCount);

	for(int i=0; i<ArgCount; ++i){
		if(strlen(const_cast<const char*>(ArgVal[i]))==0){
			ArgValues[i] = EMPTY_ERR;
			continue;
		}
		ArgValues[i] = std::string(ArgVal[i]);
	}
}

std::string ArgP::ArgumentParser::operator[](int index){
	if(index>=max){
		return OFB_ERR;
	}
	return this->ArgValues[index];
}

 

Nie wiem gdzie popełniłem błąd.

 

Z góry dziękuję każdej osobie która poświęciła swój czas.

 

Pozdrawiam.

 

PS program kompiluję z konsoli:

g++ -std=c++17 main.cpp

MinGW:

g++ (MinGW.org GCC-6.3.0-1) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

 

komentarz 27 kwietnia 2018 przez Patrycjerz Mędrzec (192,320 p.)
Jak kompilujesz swój program?
komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)

program kompiluję z konsoli:

g++ -std=c++17 main.cpp

MinGW:

g++ (MinGW.org GCC-6.3.0-1) 6.3.0 
Copyright (C) 2016 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

1
komentarz 27 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)

@Swipeyro, strażników dodaj lub pragma once

komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)
Problem już rozwiązany, źle kompilowałem projekt.

A z tą pragmą, to bym się tak nie cisnął, bo nie potrafię ogarnąć co to.
3
komentarz 27 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)

W nagłówkach których używasz wiele razy, trzeba uniknąć cyklicznego włączania bo wynikają z tego błędy. Stąd dodanie się do nich na początku:

#ifndef HEADER_UNIQE_NAME_HPP_
#define HEADER_UNIQUE_NAME_HPP_

// ... header body...

#endif // HEADER_UNIQUE_NAME_HPP_

lub... 

#pragma once

// .. header body... 

Pierwszy przykład nazywany jest "strażnikiem kompilacji".. 

komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)
Ok, dzięki.
komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)

A w sumie dobra, żeby nie tworzyć nowego tematu. Ogólnie to co teraz piszę, oprócz tego, że jest mi potrzebne, to jeszcze chcę tutaj poćwiczyć skilla. Chciałbym napisać operator <<, ale nie wiem jak to zrobić:
 

std::ostream& ArgP::ArgumentParser::operator<<(std::ostream &output){
	std::string RetVal = "";
	std::vector<std::string>::iterator i;
	auto end = ArgValues.end();
	for(auto i=ArgValues.begin(); i!=end; ++i){
		RetVal+=*i;
		RetVal+=", ";
	}
	return output << RetVal;
}

Chodzi tu o to, aby ładnie po przecinku zostały wypisane wszystkie. A tu w trzy kije błędów. Nie będę wklejał, bo szkoda miejsca, tutaj część:

main.cpp: In function 'int main(int, char**)':
main.cpp:27:11: error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'ArgP::ArgumentParser')
  std::cout<<Args;
  ~~~~~~~~~^~~~~~
In file included from a:\programy\mingw\lib\gcc\mingw32\6.3.0\include\c++\iostream:39:0,
                 from main.cpp:1:
a:\programy\mingw\lib\gcc\mingw32\6.3.0\include\c++\ostream:628:5: note: candidate: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = ArgP::ArgumentParser] <near match>
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^~~~~~~~

 

komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)

Dodatkowo nie wiem czemu, ale nie dochodzi mi do tego if'a:

int main(int argc, char* argv[]){
	ArgP::ArgumentParser Args(argc, argv);

	if(Args[1]=="config"){
		if(Args[2]==Args.EMPTY_ERR){ <------- TUTAJ
			std::cout<<"Hello.";
			color(12);
			std::cout<<"\tSecond argument is empty.";
			exit(12);
		}
		std::ofstream OutConfig("D:\\ProgramData\\AutoUSB\\config.txt");
		OutConfig<<Args[2];
	}
}

W ogóle dalej nic się nie wykonuje.

Pomożecie?

 

(Sprawdzałem, string był taki jaki miał być itd.)

1 odpowiedź

+1 głos
odpowiedź 27 kwietnia 2018 przez Patrycjerz Mędrzec (192,320 p.)
wybrane 27 kwietnia 2018 przez Hiskiel
 
Najlepsza

Musisz wprowadzić wszystkie pliki źródłowe programu, nie tylko main.cpp. Oznacza to

g++ -std=c++17 main.cpp ArgParser.cpp -o program
komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)

Dobra, dzięki. Ale teraz dostaję takie błędy:

D:\AppData\Tmp\ccpbshjg.o:argparser.cpp:(.bss+0x0): multiple definition of `ArgP
::EMPTY_ERR[abi:cxx11]'
D:\AppData\Tmp\ccjbLvUH.o:main.cpp:(.bss+0x0): first defined here
D:\AppData\Tmp\ccpbshjg.o:argparser.cpp:(.bss+0x18): multiple definition of `Arg
P::OFB_ERR[abi:cxx11]'
D:\AppData\Tmp\ccjbLvUH.o:main.cpp:(.bss+0x18): first defined here
collect2.exe: error: ld returned 1 exit status

 2 miesiące pisania i zero doświadczenia laugh

1
komentarz 27 kwietnia 2018 przez Patrycjerz Mędrzec (192,320 p.)
Dwukrotnie deklarujesz zmienne globalne EMPTY_ERR i OFB_ERR. A dlaczego? Otóż każdy moduł (plik cpp) jest kompilowany oddzielnie. Do obu dołączasz te same nagłówki, co powoduje stworzenie zmiennych dla każdego modułu oddzielnie. Później linker wariuje i nie wie, co zrobić. Najlepiej przenieś te zmienne do definicji klasy.
komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)
Dobrze. Dziękuję bardzo. Teraz wszystko ładnie działa, ale.. Jest kolejny problem.

Nie wiem czy to wina klasy, czy co, ale kiedy argumentów jest 6 (razem z nazwą programu) to program wywala.
komentarz 27 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)
Dobra, już nie ważne.

Wyrzuciłem tego reserv'a i dodawałem przez push_backa (w konstruktorze).

Wiesz dlaczego mogło się tak stać?

Podobne pytania

0 głosów
1 odpowiedź 403 wizyt
pytanie zadane 6 grudnia 2019 w C i C++ przez Gildin1_2 Gaduła (3,060 p.)
0 głosów
1 odpowiedź 179 wizyt
pytanie zadane 19 kwietnia 2021 w PHP przez Filipczak Gaduła (4,020 p.)
+2 głosów
1 odpowiedź 722 wizyt
pytanie zadane 11 kwietnia 2021 w C i C++ przez Dawidziu Bywalec (2,610 p.)

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...