最简单的传递引用需要什么?
What is needed for the simplest pass-by-reference?
我是 C++ 的新手。我对 Java 和 Python 很满意,我正在尝试快速入门 C++。
我想弄清楚如何 declare/define 一个非成员函数,该函数通过引用将参数传递给 class 对象。我无法编译我的代码。我试图在下面的三个文件集中复制问题。
我将 eclipse (Luna) 用作 IDE,后者又在 Ubuntu 14.04 上使用 g++。在这个集合中,我在 MyTest.h 中的非成员函数声明中遇到了一个神秘的编译错误,就像
"explicit qualification in the declaration of 'void mytest::printInt(ostream&, MyTest&)"
在我真实世界的例子中,我在这个函数的类似物的定义(不是声明)中遇到了一个非常相似的错误。
最初我认为这与我阻止编译器创建默认构造函数和 "MyTest& m" 以某种方式需要默认构造函数有关(尽管这对我来说完全没有任何意义)。但是声明和定义默认构造函数并不能改变问题。
我做错了什么?
定义将 class 对象作为引用参数的非成员函数的正确方法是什么?
从中可以吸取哪些更大的教训?
在文件 Mytest.h 中:
#ifndef MYTEST_H_
#define MYTEST_H_
#include<iostream>
namespace mytest {
using std::ostream;
class MyTest {
public:
MyTest(int a) : a(a) {}
int getA() { return a; }
private:
int a;
};
void mytest::printInt(ostream& os, mytest::MyTest& m);
} /* namespace mytest */
#endif /* MYTEST_H_ */
在文件中 MyTest.cpp
#include "MyTest.h"
namespace mytest {
void mytest::printInt(ostream& os, MyTest& m){
os << m.getA();
}
} /* namespace mytest */
最后一个文件给运行他们,Test.cpp:
#include "MyTest.h"
using mytest::MyTest;
using std::cout;
using std::endl;
int main(void) {
MyTest a = MyTest(1);
mytest::printInt(cout, a);
}
在 printInt 函数的声明和定义中,从函数名中删除 "mytest::"。由于命名空间块,它已经在 mytest 命名空间中。
您不应从命名空间中添加命名空间限定符:
namespace mytest {
using std::ostream;
class MyTest {
public:
MyTest(int a) : a(a) {}
int getA() { return a; }
private:
int a;
};
// no namespace qualifier here
void printInt(ostream& os, MyTest& m);
} /* namespace mytest */
namespace mytest {
// no namespace qualifier here
void printInt(ostream& os, MyTest& m){
os << m.getA();
}
然后:
using mytest::MyTest;
using std::cout;
using std::endl;
int main(void) {
MyTest a = MyTest(1);
mytest::printInt(cout, a); // now use the namespace qualifier
}
在MyTest.h
和MyTest.cpp
中替换
void mytest::printInt(ostream& os, mytest::MyTest& m)
和
void printInt(ostream& os, mytest::MyTest& m)
mytest::
不需要,因为您的声明和定义已经在命名空间块中。
附带说明一下,我建议(有时)使用 Clang 来处理不那么神秘的错误消息。 Clang 对这一行说:
./MyTest.h:18:14: error: out-of-line declaration of 'printInt' does not match any declaration in namespace 'mytest'
void mytest::printInt(ostream& os, mytest::MyTest& m);
^~~~~~~~
与 GCC 的
MyTest.h:18:53: error: explicit qualification in declaration of ‘void mytest::printInt(std::ostream&, mytest::MyTest&)’
void mytest::printInt(ostream& os, mytest::MyTest& m);
哟吼,我明白了。正如 Galik 所指出的,我的 Makefile 很糟糕。将 MyTest.o 添加到 OBJS 列表修复了它。
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJS = Test.o MyTest.o
LIBS =
TARGET = Test
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
我是 C++ 的新手。我对 Java 和 Python 很满意,我正在尝试快速入门 C++。
我想弄清楚如何 declare/define 一个非成员函数,该函数通过引用将参数传递给 class 对象。我无法编译我的代码。我试图在下面的三个文件集中复制问题。
我将 eclipse (Luna) 用作 IDE,后者又在 Ubuntu 14.04 上使用 g++。在这个集合中,我在 MyTest.h 中的非成员函数声明中遇到了一个神秘的编译错误,就像 "explicit qualification in the declaration of 'void mytest::printInt(ostream&, MyTest&)"
在我真实世界的例子中,我在这个函数的类似物的定义(不是声明)中遇到了一个非常相似的错误。
最初我认为这与我阻止编译器创建默认构造函数和 "MyTest& m" 以某种方式需要默认构造函数有关(尽管这对我来说完全没有任何意义)。但是声明和定义默认构造函数并不能改变问题。
我做错了什么? 定义将 class 对象作为引用参数的非成员函数的正确方法是什么? 从中可以吸取哪些更大的教训?
在文件 Mytest.h 中:
#ifndef MYTEST_H_
#define MYTEST_H_
#include<iostream>
namespace mytest {
using std::ostream;
class MyTest {
public:
MyTest(int a) : a(a) {}
int getA() { return a; }
private:
int a;
};
void mytest::printInt(ostream& os, mytest::MyTest& m);
} /* namespace mytest */
#endif /* MYTEST_H_ */
在文件中 MyTest.cpp
#include "MyTest.h"
namespace mytest {
void mytest::printInt(ostream& os, MyTest& m){
os << m.getA();
}
} /* namespace mytest */
最后一个文件给运行他们,Test.cpp:
#include "MyTest.h"
using mytest::MyTest;
using std::cout;
using std::endl;
int main(void) {
MyTest a = MyTest(1);
mytest::printInt(cout, a);
}
在 printInt 函数的声明和定义中,从函数名中删除 "mytest::"。由于命名空间块,它已经在 mytest 命名空间中。
您不应从命名空间中添加命名空间限定符:
namespace mytest {
using std::ostream;
class MyTest {
public:
MyTest(int a) : a(a) {}
int getA() { return a; }
private:
int a;
};
// no namespace qualifier here
void printInt(ostream& os, MyTest& m);
} /* namespace mytest */
namespace mytest {
// no namespace qualifier here
void printInt(ostream& os, MyTest& m){
os << m.getA();
}
然后:
using mytest::MyTest;
using std::cout;
using std::endl;
int main(void) {
MyTest a = MyTest(1);
mytest::printInt(cout, a); // now use the namespace qualifier
}
在MyTest.h
和MyTest.cpp
中替换
void mytest::printInt(ostream& os, mytest::MyTest& m)
和
void printInt(ostream& os, mytest::MyTest& m)
mytest::
不需要,因为您的声明和定义已经在命名空间块中。
附带说明一下,我建议(有时)使用 Clang 来处理不那么神秘的错误消息。 Clang 对这一行说:
./MyTest.h:18:14: error: out-of-line declaration of 'printInt' does not match any declaration in namespace 'mytest'
void mytest::printInt(ostream& os, mytest::MyTest& m);
^~~~~~~~
与 GCC 的
MyTest.h:18:53: error: explicit qualification in declaration of ‘void mytest::printInt(std::ostream&, mytest::MyTest&)’
void mytest::printInt(ostream& os, mytest::MyTest& m);
哟吼,我明白了。正如 Galik 所指出的,我的 Makefile 很糟糕。将 MyTest.o 添加到 OBJS 列表修复了它。
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJS = Test.o MyTest.o
LIBS =
TARGET = Test
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)