在调试程序的核心转储之一时,我遇到了多态的包含对象失去其VPTr的情况,我可以看到它指向NULL.
当一个对象丢失其VPTr时可能出现的情况.
先谢谢,Brijesh
#include <cstdio>
using namespace std;
class A {
public:
virtual void func() { printf("A::func()"); }
};
class B : public A {
public:
virtual void func() { printf("B::func()"); }
};
int main() {
A a = *(A *)new B();
a.func();
}
Run Code Online (Sandbox Code Playgroud)
问题很简单:为什么即使包含B类对象,也要a->func()调用类中的函数?Aa
简短描述:
我正在迭代向量,在向量中的每个对象上调用虚函数,以便执行一系列动作.向量是基类,迭代器也是.所有的对象都是孩子.当调用虚函数时,它执行基类的函数.
(真的)长描述:我试图模拟一个有一系列行为的生物.我的基类是抽象的,只有两个函数(虚拟),所有子类都被覆盖了:
class Behavior
{
public:
Behavior();
~Behavior(void){}
virtual void execute(){}
virtual BEHAVIOR_TYPE getType() {return m_Type;}
protected:
BEHAVIOR_TYPE m_Type;
};
Run Code Online (Sandbox Code Playgroud)
我创造了许多孩子的行为,比如移动,消费,侦察等.
class Move :
public Behavior
{
public:
BEHAVIOR_TYPE getType() {return m_Type;}
enum Direction {N, NE, E, SE, S, SW, W, NW};
Move(DOCO * d);
~Move(void);
void execute() ;
Direction chooseDirection();
void setDirection(Direction newDirection);
private:
Direction m_Direction;
DOCO *I;
BEHAVIOR_TYPE m_Type;
};
Run Code Online (Sandbox Code Playgroud)
我创建了一个向量,我在其上推送了每个Behavior子类的实例以及遍历它的迭代器:
vector<Behavior> m_Behavior;
vector<Behavior>::iterator bIt;
Run Code Online (Sandbox Code Playgroud)
当生物获得动作序列时,我尝试迭代向量,取消引用迭代器,并调用执行函数:
void World::justDoIt()
{
for(dIt=myDOCO.begin(); dIt!=myDOCO.end(); ++dIt)
{
vector<Behavior>::iterator myBehavior=(dIt)->getFirstBehavior();
vector<Behavior>::iterator end=(dIt)->getLastBehavior(); …Run Code Online (Sandbox Code Playgroud) 假设我有两个类A,而B. B.从A派生.A没有数据成员,但B有两个整数成员.
如果我在A类中定义一个方法,如下所示:
void CopyFrom( const A* other )
{
*this = *other;
}
Run Code Online (Sandbox Code Playgroud)
并在子类中调用它,整数数据成员是否会被复制?
考虑一下这段代码:
#include <vector>
#include <iostream>
using namespace std;
class Base
{
char _type;
public:
Base(char type):
_type(type)
{}
~Base() {
cout << "Base destructor: " << _type << endl;
}
};
class uncopyable
{
protected:
uncopyable() {}
~uncopyable() {}
private:
uncopyable( const uncopyable& );
const uncopyable& operator=( const uncopyable& );
};
class Child : public Base, private uncopyable
{
int j;
public:
Child():
Base('c')
{}
~Child() {
cout << "Child destructor" << endl;
}
};
int main()
{
vector<Base> v; …Run Code Online (Sandbox Code Playgroud) 我有一个棘手的情况.它的简化形式是这样的
class Instruction
{
public:
virtual void execute() { }
};
class Add: public Instruction
{
private:
int a;
int b;
int c;
public:
Add(int x, int y, int z) {a=x;b=y;c=z;}
void execute() { a = b + c; }
};
Run Code Online (Sandbox Code Playgroud)
然后在一个班级我做一些像......
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
Run Code Online (Sandbox Code Playgroud)
而在另一堂课......
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
Run Code Online (Sandbox Code Playgroud)
他们以某种方式分享这个教学载体.我担心的是我执行"执行"功能的部分.它会起作用吗?它会保留其添加类型吗?
我目前正在调查多态类型和赋值操作之间的相互作用.我主要担心的是有人是否可能尝试将基类的值分配给派生类的对象,这会导致问题.
从这个答案中我了解到,基类的赋值运算符总是被派生类的隐含定义的赋值运算符隐藏.因此,对于赋值给简单变量,不正确的类型将导致编译器错误.但是,如果通过引用进行赋值,则情况并非如此:
class A { public: int a; };
class B : public A { public: int b; };
int main() {
A a; a.a = 1;
B b; b.a = 2; b.b = 3;
// b = a; // good: won't compile
A& c = b;
c = a; // bad: inconcistent assignment
return b.a*10 + b.b; // returns 13
}
Run Code Online (Sandbox Code Playgroud)
这种形式的赋值可能会导致不一致的对象状态,但是没有编译器警告,并且代码看起来对我来说是非邪恶的.
是否有任何成熟的习惯用于检测此类问题?
我想我只能希望运行时检测,如果我找到这样一个无效的赋值就抛出异常.我刚才能想到的最好的方法是基类中的用户定义的assigment运算符,它使用运行时类型信息来确保this实际上是指向base实例的指针,而不是派生类的指针,然后执行手动逐个成员的副本.这听起来像很多开销,严重影响代码可读性.有更容易的事吗?
编辑:由于某些方法的适用性似乎取决于我想做什么,这里有一些细节.
我有两个数学概念,比如环和场.每个领域都是一个环,但不是相反.有几种实施方式中的每个,并且它们共享共同的基类,即AbstractRing和AbstractField,从前者衍生后者.现在我尝试实现基于的易于编写的引用语义 …
我遇到了这个问题,我想将不同的类(共享相同的接口)存储到一个公共容器中。
在现代 C++ 中可以做到这一点吗?
当我不想将对象存储为指针时,是否允许这样做?如果我必须使用指针,那么推荐或更简洁的方法应该是什么?
处理此类用例的正确方法应该是什么?
#include <iostream>
#include <string>
#include <vector>
enum class TYPES: int {TYPE1 = 0, TYPE2, INVALID};
class IObj
{
public:
virtual auto ObjType(void) -> TYPES = 0;
};
class InterfaceObj: IObj
{
public:
virtual auto Printable(void) -> void = 0;
};
class InterfaceTesla
{
public:
virtual auto Creatable(void) -> void = 0;
};
class CObj: InterfaceObj
{
private:
std::string msg;
public:
CObj()
{
msg = "Elon Mask!";
}
virtual auto ObjType(void) -> TYPES override
{ …Run Code Online (Sandbox Code Playgroud) 我正在制作国际象棋游戏,我希望有一系列作品.
如果我是对的,在Java中你可以拥有一个抽象Piece类并拥有King或Queen扩展该类.如果我做的阵列Piece的I可以放置一个King数组中的一块地方和Queen在另一个地方,因为这两个部分King和Queen延伸Piece.
有没有办法用C++中的结构做到这一点?
关于方法重写和OOP原则的有效性,我有一点混乱.我知道关于密封,阴影,覆盖,虚拟等的一切,但我遇到了一个场景,这让我很困惑.假设我有:
class classA
{
public virtual void sayhello()
{
Console.WriteLine("hello I'm A");
}
};
class classB :classA
{
public override void sayhello()
{
Console.WriteLine("hello I'm B");
}
};
class Program
{
static void Main(string[] args)
{
classB a = new classB();
a.sayhello();
}
}
Run Code Online (Sandbox Code Playgroud)
根据我到目前为止研究的所有内容,可以使用子类中的override关键字覆盖声明为virtual或abstract(在抽象类中)的方法.根据这个,上面的代码工作完美.当我删除virtual关键字,然后尝试使用override关键字覆盖该方法时,编译器会给出错误:
不能覆盖继承的成员'inheritence.classA.sayhello()',因为它没有标记为虚拟,抽象或覆盖
然后我从子类中删除了覆盖关键字,并将实现提供为:
class classB :classA
{
public void sayhello()
{
Console.WriteLine("hello I'm B");
}
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,该方法可以被覆盖.我能够覆盖不是虚拟或抽象的方法.所以,我的问题是:
1. …