我得到了一个编译器警告,我在这种情况下不理解.当我从以下代码编译"Child.cpp"时.(不要错过:我将我的课堂声明剥离到最低限度,所以内容没有多大意义,但你会更快地看到问题).我在最高警告级别上使用Visual Studio 2003和Visual Studio 2008收到警告.
AbstractClass.h:
#include <iostream>
template<typename T>
class AbstractClass
{
public:
virtual void Cancel(); // { std::cout << "Abstract Cancel" << std::endl; };
virtual void Process() = 0;
};
// Outside definition. If I comment out this and take the inline
// definition like above (currently commented out), I don't get
// a compiler warning.
template<typename T>
void AbstractClass<T>::Cancel()
{
std::cout << "Abstract Cancel" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
Child.h:
#include "AbstractClass.h"
class Child …Run Code Online (Sandbox Code Playgroud) 我对虚拟基类的工作原理有点困惑.特别是,我想知道如何调用基类的构造函数.我写了一个例子来理解它:
#include <cstdio>
#include <string>
using std::string;
struct A{
string s;
A() {}
A(string t): s(t) {}
};
struct B: virtual public A{
B(): A("B"){}
};
struct C: virtual public A {};
struct D: public B, public C {};
struct E: public C, public B {};
struct F: public B {};
int main(){
D d;
printf("\"%s\"\n",d.s.c_str());
E e;
printf("\"%s\"\n",e.s.c_str());
F f;
printf("\"%s\"\n",f.s.c_str());
B b;
printf("\"%s\"\n",b.s.c_str());
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
""
""
""
"B"
Run Code Online (Sandbox Code Playgroud)
我不确定前两种情况会发生什么,但对于第三种情况,我至少期待输出为"B".所以现在我只是感到困惑.理解A的构造函数如何被调用的规则是什么?
对此问题的后续问题.
基本上,在下面的代码,为什么编译器还认为,B内部A<B>的C构造函数指的(无法访问)构造函数B的基类?
struct B{};
template <typename T>
struct A : private T{};
struct C : public A<B>{
C(A<B>); // ERROR HERE
};
Run Code Online (Sandbox Code Playgroud)
Ideone上的实例.输出:
prog.cpp:1:9:错误:'struct BB :: B'无法访问
prog.cpp:7:7:错误:在此上下文中
请注意,如果你改变了构造函数参数相同的错误弹出A<B*>,A<B&>甚至A<const B>.另请注意,MSVC10,GCC 4.7和Clang 3.1 ToT中的三个将出错,因此它必须是C++规范中的内容.它是什么?
我不知道这是否可行,但我试图从Derived Class中获取Base Class实例.在C#中,我可以使用base关键字来访问Base Class的属性和方法(当然),但我想使用base本身.尝试这样做会导致"使用关键字'base'在此上下文中无效"错误.
示例代码
public class SuperParent
{
public int SPID;
public SuperParent()
{
}
}
public class SubChild : SuperParent
{
public SubChild(int pSPID)
{
base.SPID = pSPID;
}
public int BaseSPID
{
get
{
SuperParent sp = base;
return sp.SPID;
}
}
}
Run Code Online (Sandbox Code Playgroud) 在模板duck-typing和纯虚基类继承之间进行选择的指导原则是什么?例子:
// templates
class duck {
void sing() { std::cout << "quack\n"; }
};
template<typename bird>
void somefunc(const bird& b) {
b.sing();
}
// pure virtual base class
class bird {
virtual void sing() = 0;
};
class duck : public bird {
void sing() { std::cout << "quack\n"; }
}
void somefunc(const bird& b) {
b.sing();
}
Run Code Online (Sandbox Code Playgroud) 这可能看起来相当新手问题,但你能解释为什么方法Der.B()无法通过Base类变量访问受保护的Foo吗?这对我来说很奇怪:
public class Base
{
protected int Foo;
}
public class Der : Base
{
private void B(Base b) { Foo = b.Foo; } // Error: Cannot access protected member
private void D(Der d) { Foo = d.Foo; } // OK
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在尝试实现命令设计模式,但我遇到了一个概念问题.假设您有一个基类和一些子类,如下例所示:
class Command : public boost::noncopyable {
virtual ResultType operator()()=0;
//Restores the model state as it was before command's execution.
virtual void undo()=0;
//Registers this command on the command stack.
void register();
};
class SomeCommand : public Command {
virtual ResultType operator()(); // Implementation doesn't really matter here
virtual void undo(); // Same
};
Run Code Online (Sandbox Code Playgroud)
问题是,每次()在SomeCommand实例上调用操作符时,我都想通过调用Command的register方法将*this添加到堆栈中(主要用于撤消).我想避免从SomeCommand :: operator()()调用"register",但要将它命名为automaticaly(someway ;-))
我知道当你构造一个像SomeCommand这样的子类时,基类构造函数被称为automaticaly,所以我可以在那里添加一个"register"调用.在调用operator()()之前,我不想调用它.
我怎样才能做到这一点?我想我的设计有些缺陷,但我真的不知道如何使这项工作.
我应该以哪种方式访问此父方法和父变量?
class Base
{
public:
std::string mWords;
Base() { mWords = "blahblahblah" }
};
class Foundation
{
public:
Write( std::string text )
{
std::cout << text;
}
};
class Child : public Base, public Foundation
{
DoSomething()
{
this->Write( this->mWords );
// or
Foundation::Write( Base::mWords );
}
};
Run Code Online (Sandbox Code Playgroud)
谢谢.
编辑:如果有歧义怎么办?
如果我要创建一个名为基类base和派生类叫derived_1,derived_2等...我用的是基类的实例的集合,然后当我取回的元素,并尝试使用它,我会发现C++认为它的类型是基类的,可能是因为我从一个基类中检索到它std::vector.当我想使用仅存在于特定派生类的特征时,这是一个问题,我知道这个对象是我将它放入向量时的类型.
所以我将元素转换为它应该是的类型,并发现这不起作用.
(derived_3)obj_to_be_fixed;
Run Code Online (Sandbox Code Playgroud)
并记得这是一个指针的事情.经过一些调整后,现在已经奏效了.
*((derived_3*)&obj_to_be_fixed);
Run Code Online (Sandbox Code Playgroud)
这是正确的,还是有一个abc_cast()功能可以减少混乱?
编辑:
我不得不把它扩展到另一个问题,那里展示了完整的解决方案.stackoverflow.com ... why-the-polymorphic-types-error-and-cleanup-question
struct B { int b1, b2; B(int, int); };
struct D : B {
int d1, d2;
// which is technically better ?
D (int i, int j, int k, int l) : B(i,j), d1(k), d2(l) {} // 1st Base
// or
D (int i, int j, int k, int l) : d1(k), d2(l), B(i,j) {} // last Base
};
Run Code Online (Sandbox Code Playgroud)
以上只是伪代码.实际上我想知道调用基础构造函数的顺序是否重要? 是否有任何不良行为(特别是拐角案件)由任何案件引起?我的问题是更多的技术方面,而不是编码风格.
base-class ×10
c++ ×8
inheritance ×4
templates ×3
c# ×2
class ×2
.net ×1
c++11 ×1
casting ×1
constructor ×1
methods ×1
parent-child ×1
protected ×1
pure-virtual ×1
scope ×1
virtual ×1