我试图让一个类的每个实例(Caller在这里命名)都有另一个类的实例(Target).关键是第二类有很多孩子,我需要能够让Caller他们随意切换班级.我尝试了几种方法,但没有一种方法给了我任何理想的结果.当前代码:
class Target
{
public:
virtual void do_something()
{ log_message("NO!"); }
};
class TargetChild : public Target
{
public:
virtual void do_something()
{ log_message("YES!"); }
};
class Caller
{
private:
Target target;
public:
void call_target()
{ target.do_something(); }
void set_target(Target set_target)
{ target = set_target; }
};
int main( int argc, const char* argv[] )
{
TargetChild targetChild;
Caller caller;
caller.call_target();
caller.set_target(targetChild);
caller.call_target();
}
Run Code Online (Sandbox Code Playgroud)
日志文件中的结果是"NO!YES!" 但它写了NO!两次.我真的不明白它有什么问题.
class classa {
public:
virtual void foo();
};
class classb : public classa {
public:
virtual void foo() override;
};
void classa::foo()
{
std::cout << "foo from a" << std::endl;
}
void classb::foo()
{
std::cout << "foo from b" << std::endl;
}
int main()
{
std::vector<classa> stuff;
classa a;
classb b;
stuff.push_back(a);
stuff.push_back(b);
stuff[0].foo();
stuff[1].foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期望上面的代码返回
foo from a
foo from b
Run Code Online (Sandbox Code Playgroud)
但它同时返回foo from a.
我认为这是因为矢量存储classa但我不确定.我该如何classb:foo()被召唤b?
我被困了,已经尝试了很多来解决这个"虚拟"问题,所以我求求你帮助我,因为它可能是一个愚蠢的"受过训练的眼睛"可以在几秒钟内解决..
问题:当我在main中执行以下操作时:
PrologConnector swiProlog;
swiProlog = PrologConnector::connectorFactory(PrologConnector::swi,argv);
swiProlog.send("blabla");
Run Code Online (Sandbox Code Playgroud)
始终调用PrologConnector类的send方法,但不调用子类中的方法..您是否看到了问题?
谢谢您的帮助!!
这是代码:PrologConnector.h
class PrologConnector {
virtual int send(char * cmd);
virtual int init(char **argv);
static PrologConnector connectorFactory(Prolog prolog, char ** argv);
};
Run Code Online (Sandbox Code Playgroud)
PrologConnector.cpp
int PrologConnector::send(char * argv) {
std::cout << "not wanted"<<std::endl;
return 0;
}
int PrologConnector::init(char **argv) {
//TODO add implementation
return 0;
}
PrologConnector PrologConnector::connectorFactory(Prolog prolog, char **argv) {
if (prolog == swi) {
SWIConnector sc;
sc.init(argv);
return sc;
}
std::cout <<"Error in initialization!"<<std::endl;
PrologConnector pc;
return pc;
} …Run Code Online (Sandbox Code Playgroud) 复制构造函数传统上在C ++程序中无处不在。但是,我怀疑自C ++ 11起是否有充分的理由。
即使程序逻辑不需要复制对象,通常也仅出于对象重新分配的目的而包含复制构造函数(通常是默认值)。没有复制构造函数,您将无法将对象存储在中,甚至无法从函数返回对象。std::vector
但是,自C ++ 11起,移动构造函数一直负责对象的重新分配。
复制构造函数的另一个用例就是简单地复制对象。但是,我非常确信a .copy()或.clone()method比复制构造函数更适合该角色,因为...
复制对象并不常见。当然,有时有时对象的接口必须包含“复制自己”的方法,但这只是有时。在这种情况下,显式胜于隐式。
有时,一个对象可能会公开几种不同.copy()的方法,因为在不同的上下文中,副本可能需要以不同的方式创建(例如,更浅或更深)。
在某些情况下,我们希望这些.copy()方法完成与程序逻辑相关的重要工作(增加一些计数器,或者为副本生成一个新的唯一名称)。我不会接受任何在复制构造函数中具有非显而易见逻辑的代码。
最后但并非最不重要的一点是,.copy()如果需要,一种方法可以是虚拟的,从而可以解决切片问题。
我实际想要使用复制构造函数的唯一情况是:
vec3 b = a.copy()太冗长。旁注:我已经考虑过CAS需要复制构造函数这一事实,但出于
operator=(const T&)完全相同的推理,我认为CAS是必需的;如果您确实需要此,则首选
.copy()+operator=(T&&) = default。)
对我而言,这足以激励T(const T&) = delete默认情况下在任何地方使用并.copy()在需要时提供一种方法。(也许也private T(const T&) = default只是能够写copy()或virtual copy()没有样板。)
问:以上推理是否正确,或者我是否缺少逻辑对象实际需要或从复制构造函数中以某种方式受益的任何充分理由?
具体来说,我是否正确,因为移动构造函数完全取代了C ++ 11中的对象重新分配的职责?当对象需要在不更改其状态的情况下在内存中的其他位置移动时,我会在所有情况下非正式地使用“重新分配”。
我从学校工作中获得了一些 C++ 经验。我了解到,除其他外,对象应该作为指针存储在容器(向量、映射等)中。主要原因是我们需要使用 new-operator 和复制构造函数,以便在对象的堆(也称为动态内存)上创建副本。此方法还需要定义析构函数。
但是,从那以后我读到的内容看来,STL 容器似乎已经将它们包含的值存储在堆上。因此,如果我将对象存储为值,无论如何都会在堆上创建一个副本(使用复制构造函数),并且不需要定义析构函数。总而言之,无论如何都会在堆上创建一个副本???
此外,如果(真),那么我能想到的使用指针存储对象的唯一其他原因是减轻复制容器的资源需求,因为指针比整个对象更容易复制。但是,这将需要使用 std::shared_ptr 而不是常规指针,因为您不希望在原始容器被销毁时删除复制容器中的元素。这种方法还可以减少定义析构函数的需要,不是吗?
编辑:要定义的析构函数将用于使用容器的类,而不是用于存储对象的类。
编辑 2:我想一个更精确的问题是:“从内存和资源使用的角度来看,使用 new 运算符将对象存储为指针,而不是普通值,这有什么不同吗?”
假设我有一个基类和一个派生类:
class Base
{
public:
virtual ~Base() {}
virtual void DoSomething() = 0;
};
class Child : public Base
{
public:
virtual void DoSomething()
{
// Do Something
}
};
Run Code Online (Sandbox Code Playgroud)
使用指向派生类实例的指针初始化基类类型的std :: auto_ptr是否安全?IE会像这样创建一个对象:
std::auto_ptr<Base> myObject(new Derived());
Run Code Online (Sandbox Code Playgroud)
正确调用派生类的析构函数而不是基类而不泄漏内存?
为什么要删除默认副本并移动基类的ctor和赋值?
这是来自Stroustrup的书(第4版c ++).
通常基类是抽象的,所以当你甚至无法实例化它们时,为什么你会担心这一点.
class Pet {
public:
virtual string getDescription() const {
return "This is Pet class";
}
};
class Dog : public Pet {
public:
virtual string getDescription() const {
return "This is Dog class";
}
};
Run Code Online (Sandbox Code Playgroud)
假设我有一个函数,它接受基类类型的参数
void describe(Base obj) {
p.getDescription();
}
Run Code Online (Sandbox Code Playgroud)
我在这个函数中传递派生类对象,所以对象将被切片,我们将输出重新调整到基类.
但是,如果我修改这个功能,并使它像
void describe(Base& obj) {
p.getDescription();
}
Run Code Online (Sandbox Code Playgroud)
并再次传递派生类对象,此时输出将是派生类.
我无法理解引用传递如何避免对象切片.
考虑一些抽象类A:
class A
{
virtual void f() = 0;
};
Run Code Online (Sandbox Code Playgroud)
假设我希望声明一个返回此类的函数签名类型:
using Type = A();
Run Code Online (Sandbox Code Playgroud)
鉴于此代码,gcc-4.8.2错误导致错误
error: ‘type name’ declared as function returning an abstract class type
Run Code Online (Sandbox Code Playgroud)
clang-3.3 编译得很好.
我试图谷歌这个问题,但没有找到任何有用的东西.这段代码是否符合标准?如果没有,那么禁止宣布这种签名类型的原因是什么?我只是在声明中看不到任何问题.
免责声明:我不打算创建这种类型的实例,我只想宣布描述的签名.
对于那些对这种声明有用的人感兴趣:我有一些工厂容器使用签名,就像Interface(Arguments...)添加新工厂来了解新工厂一样; 实际返回的类型是根据一个单独的traits类确定的,参数由Interface.
显然,我可以将其Interface与签名分开,但它看起来不会很好:(
我目前正在我的游戏和渲染引擎之间编写一个抽象层.不幸的是,我遇到了一个问题:我似乎无法将超类(抽象接口)强制转换为子类(具体引擎的实现).这是我的代码:
IInitationSettings.h
class IInitationSettings {};
Run Code Online (Sandbox Code Playgroud)
OxygineInitiationSettings.h
#include "IInitiationSettings.h"
#include "core/oxygine.h"
class OxygineInitiationSettings : public IInitationSettings, public oxygine::core::init_desc {
public:
OxygineInitiationSettings(const char* title, bool vsync, bool fullscreen, int width, int height);
};
Run Code Online (Sandbox Code Playgroud)
OxygineInitiationSettings.cpp
#include "OxygineInitiationSettings.h"
OxygineInitiationSettings::OxygineInitiationSettings(const char* title, bool vsync, bool fullscreen, int width, int height) : oxygine::core::init_desc() {
this->title = title;
this->vsync = vsync;
this->fullscreen = fullscreen;
this->w = width;
this->h = height;
}
Run Code Online (Sandbox Code Playgroud)
抽象的init方法:
static void init(IInitiationSettings& initSettings);
void GraphicsFactory::init(IInitiationSettings& initSettings){
#ifdef USE_OXYGINE_RENDERING
OxygineInitiationSettings settings = initSettings; //Does not …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++11 ×2
abstraction ×1
auto-ptr ×1
class ×1
clone ×1
function ×1
inheritance ×1
overriding ×1
polymorphism ×1
rendering ×1
signature ×1
stl ×1
visual-c++ ×1
windows ×1