执行以下操作是安全的还是未定义的行为:
class Base
{
private:
int a;
};
class Derived : public Base
{
private:
int b;
};
Base x;
Derived y;
x = y; // safe?
Run Code Online (Sandbox Code Playgroud)
派生类中的额外位是否会被切掉?
从C++ 11开始,人们可以写出类似的内容
#include <vector>
#include <string>
struct S
{
S(int x, const std::string& s)
: x(x)
, s(s)
{
}
int x;
std::string s;
};
// ...
std::vector<S> v;
// add new object to the vector v
// only parameters of added object's constructor are passed to the function
v.emplace_back(1, "t");
Run Code Online (Sandbox Code Playgroud)
是否有的C++函数任何C#类似物像emplace或emplace_back容器类(System.Collections.Generic.List)?
更新:
在C#中,类似的代码可能会被编写为list.EmplaceBack(1, "t");代替list.Add(new S(1, "t"));.不记得班级名称并且new ClassName每次都在这种情况下写作会很好.
它在C++ FAQ网站中提到 - "当通过值作为基类对象传递时,较大的派生类对象被切片",切片是什么意思?任何样品要展示?
http://www.parashift.com/c++-faq-lite/value-vs-ref-semantics.html#faq-31.8
我使用VSTS 2008 +本机C++作为我的开发环境.
我有一个问题,关于C++编译器如何知道在使用继承时需要为对象分配多少空间.
想象一下以下课程,对于成人和儿童来说,他们可以扩展一个Person课程,但是孩子有一本短书.
class Person
{
};
class Adult : public Person
{
//No book
};
class Child : public Person
{
char book[1000]; //Stores the book
};
Run Code Online (Sandbox Code Playgroud)
现在,如果您创建Person对象数组,并向其添加对象:
Adult adult1;
Child child1;
Person people[2];
people[0] = child1;
people[1] = adult1;
Run Code Online (Sandbox Code Playgroud)
我的问题是:编译器如何知道确保数组是连续内存块所需的空间,如果它不知道数组是否将填充Adult或Child(大小不同)对象?
我希望这有足够的意义来回答......
谢谢
我正在研究c ++的参考,现在我对变量名和引用之间的区别感到很困惑.测试代码如下:
class TestClass{
private:
int num;
public:
TestClass(int n):num(n){
cout<<this<<" : init of : " <<this->num<<endl;
}
TestClass(const TestClass& t):num(t.num){
cout<<this<<" : copyInit of : " <<this->num<<endl;
}
};
int main(int argc, const char * argv[]){
TestClass t = *(new TestClass(55)); //just to test copy initialization
const TestClass t2 = TestClass(100); //option1
const TestClass &t2 = TestClass(100); //option2
}
Run Code Online (Sandbox Code Playgroud)
所以现在我有两个制作对象的选项,它们彼此互斥.
根据我的理解,如果我使用options2,编译器会在堆栈内存中生成一个临时对象,并将参考值返回给t2.
如果这是对的,我该如何用语言表达或解释选项1?似乎在堆栈内存中创建了相同的对象,并且计算机给该对象命名为't2',但我不清楚这个option1与option2的不同之处,因为变量和引用的名称有些令人困惑.
另外,交替切换选项,我可以看到在每种情况下在不同的存储器位置创建对象.(例如,option1的对象是在0x7fff5fbff828中创建的,那个或option2是在0x7fff5fbff820中创建的)
你能解释一下吗?
1.变量名(option1)和引用(option2)之间的区别是什么.
2.选项1和2中的工作方式有何不同.
3.在任何一种情况下,为什么在不同的内存位置创建对象.
提前谢谢你的帮助!
当使用CRTP实现表达式模板时,表达式层次结构顶部的类使用从基础到派生的向下转换来实现其某些操作.根据clang-3.5(-std=c++1y),这个垂头丧气的constexpr功能应该是非法的:
test.cpp:42:16: error: static_assert expression is not an integral constant expression
static_assert(e() == 0, "");
^~~~~~~~
test.cpp:11:26: note: cannot cast object of dynamic type 'const base<derived>' to type 'const derived'
const noexcept { return static_cast<const Derived&>(*this)(); }
Run Code Online (Sandbox Code Playgroud)
GCC愉快地编译代码.那么谁是对的?如果Clang是对的,哪些C++ 14对constexpr函数的限制会使这种向下转换非法?
这是MWE:
template <class Derived>
class base
{
public:
constexpr auto operator()()
const noexcept { return static_cast<const Derived&>(*this)(); }
};
class derived : public base<derived>
{
public:
constexpr auto operator()()
const noexcept { return …Run Code Online (Sandbox Code Playgroud) 我看过很多类似的问题,但还没有找到解决我特定问题的方法.我试图SWIGify一些使用std :: function的C++ 11代码,所以我可以在我的Java应用程序中使用它.
我遇到过像这样的共享指针:
virtual std::shared_ptr<some::ns::TheThing> getTheThing(unsigned short thingID);
Run Code Online (Sandbox Code Playgroud)
并使用shared_ptr指令成功处理它们,如下所示:
%shared_ptr(some::ns::TheThing);
Run Code Online (Sandbox Code Playgroud)
我遇到过这样的共享指针向量:
virtual std::vector<std::shared_ptr<some::ns::TheThing>> getAllTheThings() const = 0;
Run Code Online (Sandbox Code Playgroud)
并使用如下模板成功处理它们:
%template(ThingVector) std::vector<std::shared_ptr<some::ns::TheThing>>;
Run Code Online (Sandbox Code Playgroud)
现在我有一个像这样的方法:
void registerThingCallback(std::function<void(std::shared_ptr<some::ns::TheThing>) > func);
Run Code Online (Sandbox Code Playgroud)
我无法让SWIG正确包装它.我已经尝试使用%回调,导演,%模板和%内联功能代码,因为我已经看到所有这些事情的例子,但是还没有能够得到任何似乎接近工作的东西.如果有帮助(清理和减少),这里有一个关于函数调用的更多上下文:
#include <functional>
namespace some {
namespace ns {
/**
* Hold some callbacks.
*/
class ThingCallbacks {
public:
/**
* Registers a callback
* @param func The callback function
*/
void registerThingCallback(std::function<void(std::shared_ptr<some::ns::TheThing>) > func);
};
}
}
Run Code Online (Sandbox Code Playgroud)
根据Flexo下面的答案,我更接近解决方案.我能够让下面的例子完全像宣传的那样工作.我尝试将它合并到我的实际代码中,但遇到了问题.为了扩展我之前的简化示例,这里是我对TheThing的定义:
#ifndef THE_THING_H
#define THE_THING_H
#include <string>
namespace some {
namespace ns …Run Code Online (Sandbox Code Playgroud) 甲派生类对象可以被分配到一个基类对象在C++中.
Derived d;
Base b = d; // It's Ok
Run Code Online (Sandbox Code Playgroud)
但为什么不能将基类对象分配给派生类对象?
Base b;
Derived d = b; //Not Ok. Compiler give an error
Run Code Online (Sandbox Code Playgroud)
编辑:
对不起,这个问题实际上是在面试时提出来的.
我正在阅读Scott Meyers撰写的Effective C ++第三版。
他说,一般来讲,从不包含虚函数的类中继承不是一个好主意,因为如果您以某种方式将派生类的指针转换为基类的指针,然后再将delete其转换,则可能会出现不确定的行为。
这是他给出的(人为)示例:
class SpecialString: public std::string{
// ...
}
SpecialString *pss = new SpecialString("Impending Doom");
std::string *ps;
ps = pss;
delete ps; // undefined! SpecialString destructor won't be called
Run Code Online (Sandbox Code Playgroud)
我理解为什么这会导致错误,但是在SpecialString类内部没有什么可以阻止类似ps = pss事件的发生?
Meyers指出(在本书的另一部分中),显式防止类中允许某些行为的常见技术是声明特定的函数,但有意不对其进行定义。他给出的例子是复制构造。例如,对于您不想允许复制构造的类,声明一个私有复制构造函数但不定义它,因此,任何使用它的尝试都会导致编译时错误。
我意识到ps = pss在此示例中不是复制构造,只是想知道是否可以在此处进行任何操作以明确防止这种情况发生(除了“只是不这样做”的答案外)。