wie umgehe ich den namespace einer Klasse ohne namespace keyword zu nutzen?
-
Hallo,
Ich lerne gerade C++ und ich will wissen wie ich wenn ich eine Klasse in einer .h datei habe es vermeiden kann immer den Klassennamen nutzen zu müssen, das ist nämlich viel schreibarbeit. Hier ist ein Beispiel:
Klassenname::function(arg1,...){...}
#ifndef GUARD_VM_h #define GUARD_VM_h #include <vector> using namespace std; enum status_code { OK, COMPILE_ERROR, RUNTIME_ERROR }; enum op_code { OP_RETURN, OP_CONSTANT, OP_NEGATE,OP_ADD, OP_SUBTRACT, OP_MULTIPLY, OP_DIVIDE, }; typedef vector<op_code> code_segment; typedef vector<double> constant_segment; typedef vector<uint64_t> code_lines; class VM { uint64_t ip; uint64_t sp; code_segment code; constant_segment constants; code_lines code_lines; vector<double> stack; public: status_code run(); void print_stack_trace(); uint64_t push(double val); double pop(); int write_to_constants(double constant); void write_constant_to_code(double constant); void write_opcode(op_code operation); }; #endif
#include "vm.h" #include <vector> #include <iostream> // hier und an vielen stellen muss VM:: stehen. Wie kann ich das vermeiden? status_code run(){ for(;;){ switch(code[ip++]){ case OP_RETURN: cout << "stack.pop() " << pop() << endl; return OK; case OP_CONSTANT: double constant = constants[code[ip++]]; push(constant); cout << "op_constant on stack:" << constant << endl; break; case OP_NEGATE: double constant = constants[code[ip++]]; push(-constant); cout << "op_negate on stack:" << constant << endl; break; case OP_MULTIPLY: double operand_B = pop(); double operand_A = pop(); push(operand_A * operand_B); break; } } } void print_stack_trace(){ for(int i = 0; i < stack.size()-1; i++){ cout << "[" << stack[i] << "]" << endl; } } uint64_t push(double val){ stack.emplace_back(val); return stack.size()-1; } double pop(){ double ret = stack[stack.size()-1]; stack.pop_back(); return ret; } int write_to_constants(double constant){ constants.emplace_back(constant); return constants.size()-1; } void write_constant_to_code(double constant){ code.emplace_back(OP_CONSTANT); code.emplace_back(write_to_constants(constant)); } void write_opcode(op_code operation){ code.emplace_back(operation); }
-
Kurze Antwort: gar nicht.
Wenn Du nur die Deklaration der Klasse in den Header schreibst, dann müssen vor den Definition der Member Functions in der .C/.cc/.cxx/.cpp Datei der jeweiligen Klassenname stehen. Willst Du das umgehen gibt es eigentlich nur den Weg Module zu nutzen, und die Deklaration und Definition in einem in die .C/.cc/.cxx/.cpp Datei zu schreiben. Das setzt aber voraus, dass der Compiler neu genug ist und er Module fehlerfrei unterstützt. GCC 14.1.0 ist der einzige Compiler mit dem ich nicht triviale Module übersetzen konnte.
-
@john-0 hey, danke. Gibt es einen Weg sich die Mühe zu sparen? Ich habe einen apple m2 laptop und nutze clang 15.0.0 .Ich glaube das ist eine compiler sammlung aber welchen einzelnen versionen das entspricht weiß ich nicht.
Noch eine Frage - wenn ich einen eingabe string habe gibt es eine möglichkeit einzelne wörter getrennt durch whitespace nacheinander auszulesen oder muss man das selber machen?
-
@fairy2211 Du könntest alternativ einen Editor verwenden, der dich bei sowas unterstützt. Autovervollständigung, Funktionsrumpf in Implementationsdatei etc ist alles keine Magie
Zu deiner zweiten Frage: Es gibt verschiedene Möglichkeiten. Zum einen hat
std::getline
ein Delim Argument:#include <iostream> #include <sstream> #include <string> int main() { std::string text = "words,split,by,comma"; std::istringstream input(text); for (std::string line; std::getline(input, line, ',');) std::cout << line << '\n'; }
In "modernem C++" mit C++23 Featuren kann man auch sowas machen:
#include <algorithm> #include <print> #include <ranges> #include <string> #include <vector> int main() { std::string text = "words,split,by,comma"; auto splitText = text | std::views::split(',') | std::ranges::to<std::vector<std::string>>(); std::ranges::for_each(splitText, [](const auto& word) { std::println("{}", word); }); }
Dafür braucht man aber einen aktuellen Compiler und muss C++ 23 aktiviert haben. Bei Microsoft mit dem Compiler Flag
/std:c++latest
Für Clang musst du da selbst nachschauenUnd, Achtung, der Code ist nicht wirklich äquivalent, der zweite Code schreibt die getrennten Teile in einen Vektor während der erste Code die Teile einfach direkt ausgibt.
-
@fairy2211, als Hinweis zu deinem Code:
Verwende niemalsusing namespace std;
in einer Headerdatei (s.a. "using namespace" in c++ headers)!Das ist zwar was du vermeiden willst (mehr Schreibarbeit), aber die explizite Angabe von
std::
in Headerdateien verhindert, daß es bei Einbindung dieser Headerdateien zu Namenskollisionen kommen kann.
-
@Schlangenmensch danke. was ist, wenn als delimiter beliebig lange leerzeichen folgen benutzt werden sollen?
-
@Th69 Danke, eigentlich habe ich das gelesen - ich habe es ausnahmsweise gemacht.
-
@fairy2211 sagte in wie umgehe ich den namespace einer Klasse ohne namespace keyword zu nutzen?:
@john-0 hey, danke. Gibt es einen Weg sich die Mühe zu sparen?
Wie ich schon schrieb – bei älterem C++ nein.
Ich habe einen apple m2 laptop und nutze clang 15.0.0 .Ich glaube das ist eine compiler sammlung aber welchen einzelnen versionen das entspricht weiß ich nicht.
Es ist die Version 15.0.0 und die dürfte zu alt sein.
-
@fairy2211 Dann schaut man sich die Regular expressions library an und löst das damit.