在将扩展对象作为参数传递给函数时,我尝试使用抽象类,但到目前为止,我的尝试导致了一些编译器错误。
我有一些关于问题所在的线索,我显然不允许实例化抽象类,我相信MyClass中的一些代码正在尝试这样做,尽管这不是我的意图。一些研究建议我应该引用对象作为指针来实现我想要的东西,但是到目前为止我的尝试都失败了,我甚至不确定这是不是答案(因此我在这里问)。
我现在要提交的是,我更熟悉Java而不是C++,我确信我的问题的一部分是由于这一点。
下面是我在我的程序中尝试做的一个例子:
class A {
public:
virtual void action() = 0;
};
class B : public A {
public:
B() {}
void action() {
// Do stuff
}
};
class MyClass {
public:
void setInstance(A newInstance) {
instance = newInstance;
}
void doSomething() {
instance.action();
}
private:
A instance;
};
int main(int argc, char** argv) {
MyClass c;
B myInstance;
c.setInstance(myInstance);
c.doSomething();
return 0;
}
这个示例产生的编译器错误与我在程序中得到的错误相同:
sean@SEAN-PC:~/Desktop$ gcc -o test test.cpp
test.cpp:20: error: cannot declare parameter ‘newInstance’ to be of abstract type ‘A’
test.cpp:2: note: because the following virtual functions are pure within ‘A’:
test.cpp:4: note: virtual void A::action()
test.cpp:30: error: cannot declare field ‘MyClass::instance’ to be of abstract type ‘A’
test.cpp:2: note: since type ‘A’ has pure virtual functions
test.cpp: In function ‘int main(int, char**)’:
test.cpp:36: error: cannot allocate an object of abstract type ‘A’
test.cpp:2: note: since type ‘A’ has pure virtual functions
更新
感谢大家的反馈。
我已经将"MyClass::instance“更改为包含一个类型为A的指针,但现在我得到了一些与vtable相关的奇怪错误:
sean@SEAN-PC:~/Desktop$ gcc -o test test.cpp
/tmp/ccoEdRxq.o:(.rodata._ZTI1B[typeinfo for B]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/tmp/ccoEdRxq.o:(.rodata._ZTI1A[typeinfo for A]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
/tmp/ccoEdRxq.o:(.rodata._ZTV1A[vtable for A]+0x8): undefined reference to `__cxa_pure_virtual'
collect2: ld returned 1 exit status
我修改后的代码如下(A、B未修改):
class MyClass {
public:
void setInstance(A* newInstance) {
instance = newInstance;
}
void doSomething() {
instance->action();
}
private:
A* instance;
};
int main(int argc, char** argv) {
MyClass c;
B myInstance;
c.setInstance(&myInstance);
c.doSomething();
return 0;
}
发布于 2009-03-16 12:07:37
你的问题是你应该在你的函数中接受一个引用。原因是引用实际上并不复制传递的参数。但是,如果您接受A
而不是引用A&
,那么您实际上复制了传递到参数对象的实参,您得到的是A
类型的对象-但这实际上是不允许的!
// the reference parameter will reference the actual argument
void setInstance(A &newInstance) {
// assign the address of the argument to the pointer member
// instance.
instance = &newInstance;
}
然后,您必须将类中的成员更改为指针。它不能是一个引用,因为setInstance
会改变它引用的内容--一个引用在其整个生命周期中只能引用一个对象,而指针可以被设置为只需重新分配一个不同的地址就可以做不同的事情。剩下的部分如下所示
void doSomething() {
// call a member function on the object pointed to
// by instance!
instance->action();
}
private:
// a pointer to some object derived from A
A *instance;
还要注意,您必须使用g++
编译C++程序,因为它还将C++标准库链接到您的代码
g++ -o test test.cpp # instead of gcc!
发布于 2009-03-16 12:00:01
您所做的在Java中是可行的,因为声明"A“类型的参数或成员变量实际上意味着”指向A的指针“。在C++中,您实际上需要明确这一点,因为它们是两个不同的东西:
void setInstance(A* newInstance) { // pointer to an "A"
instance = newInstance;
}
在宣言中:
A* instance; // Not an actual "A", but a pointer to an "A"
发布于 2009-03-16 12:11:44
我相信这就是你想要做的。它通过根据handle类是否指向B或C的实例实际打印输出来演示多态。其他人是正确的,您可能还需要一个虚拟析构函数。
这将编译为: g++ test.cpp -o测试
#include <stdio.h>
class A {
public:
virtual void action() = 0;
};
class B : public A {
public:
B() {}
void action() {
printf("Hello World\n");
}
};
class C : public A {
public:
C() {}
void action() {
printf("Goodbye World\n");
}
};
class AHandleClass {
public:
void setInstance(A *A_Instance) {
APointer = A_Instance;
}
void doSomething() {
APointer->action();
}
private:
A *APointer;
};
int main(int argc, char** argv) {
AHandleClass AHandle;
B BInstance;
C CInstance;
AHandle.setInstance(&BInstance);
AHandle.doSomething();
AHandle.setInstance(&CInstance);
AHandle.doSomething();
return 0;
}
https://stackoverflow.com/questions/650091
复制相似问题