初始化类对象
“白色雪梨”通过精心收集,向本站投稿了9篇初始化类对象,下面是小编精心整理后的初始化类对象,希望能够帮助到大家。
篇1:初始化类对象
初始化类对象赵湘宁问题:
C++中如何初始化类中的表数据?在C语言中,我能像下面这样初始化结构数组:
//struct MYSTRUCT { int x,y,z;};MYSTRUCT table[] = { { 1,2,3 }, { 4,5,6 }, ... // etc};//
但是如果MYSTRUCT是个C++类,而不是结构,我编译就会出错,我觉得这是C++的一个不足。解答:
这个问题完全取决于你如何看待C++。C++的一个优点之一便是它强制你做正确的事情。例如,C++不喜欢创建对象时不调用构造函数。这只就是为什么你不能用原始数据初始化类对象的原因,不管是部分数组还是其它数据。构造函数的目的是保证每一个对象都被正确初始化,不管你是从程序栈,可用内存堆分配空间,还是作为静态数组元素。让原始数据旁路掉构造函数被忌讳的事情。也导致你不能用初始的数据来创建对象静态数组――你必须调用构造函数!
//class CFooble { int x,y,z;public: CFooble(int xx, int yy, int zz) : x(xx),y(yy),z(zz) { ... } CFooble(int i) { x=y=z=i; }};CFooble table[] = { CFooble(1,2,3), CFooble(4,5,6), CFooble(0), // can use any constructor!};//
下面的代码是个可以编译的完整例子,
//// StaticClassArray ― 说明如何初始化在C++对象的静态C数组 // 编译方法如下://// cl fooble.cpp//#include 在C++中,你能用用任何构造函数初始化数组元素,并且C++甚至用缺省的构造函数来初始化额外的元素,而不用外部的初始华例程。对我来说,这是一种进步,而不是不足。 危害:读取未初始化的值会导致不明确甚至是半随机化的行为, 最佳处理办法:永远在使用对象之前先将它初始化;确保每一个构造函数都将对象的每一个成员初始化。 1 注意区分赋值和初始化: 从初始化的角度而言,这不是一个最佳的处理办法。虽然这会让对象的指最终为你期望的值,但是实际上,对象的成员变量的初始化动作发生在进入构造函数本体之前。而在构造函数本体之内,不是被初始化,而是被赋值。 2 较佳的写法:使用成员变量初始化列表 结果和上一个的最终结果相同,但是效率较高。 规定:总是在初值列表中列出所有成员变量,以免遗漏需要初始化的成员变量。即,总使用成员初始化列表。 一个特例再次印证了上句的价值:如果成员变量是const或reference,它们就一定需要初值,不能被赋值。 3 成员初始化次序: 一般地:base classes更早于其derived classes被初始化,而class的成员变量总是以其声明次序被初始化。 特别低:不同编译单元内定义的non-local static对象的初始化次序 解析: 1 non-local static: 包括:global对象定义于namespace作用域内的对象在classes内、在file作用域内被声明为static的对象local static对象,指在函数内被声明为static的对象, 2 编译单元:产出单一目标文件的那些源码。基本上可以认为是一个源码文件加上它所包含的头文件。 问题:C++对“不同编译单元内的non-local static对象”的初始化相对次序并无明确定义。原因:决定它们的初始化次序相当困难,甚至是无解的。解决:reference-returning函数(示例如下)原理:C++保证,函数内的local static对象会在该函数被调用期间首次遇上该对象的定义式时被初始化。 所以以函数调用替换直接的对象访问,就保证获得一个已经初始化的对象的引用。Demo: 可能会发生初始化次序问题的版本:a.cpp b.cpp 改进后的版本: 小结: 为内置类型对象进行手工初始化,以为C++不保证初始化它们;构造函数最好使用成员变量初始化列表,其排列次序应该和它们在class中的声明次序相同;为免除“跨编译单元之初始化次序”问题,请以local static对象(referance returning函数)替换non-local static对象。 参考资料: 《Effective C++ 3rd》 C++类对象内存结构 首先介绍一下C++中有继承关系的类对象内存的布局:在C++中,如果类中有虚函数,那么它就会有一个虚 函数表的指针__vfptr,在类对象最开始的内存数据中,之后是类中的成员变量的内存数据。 对于子类,最开始的内存数据记录着父类对象的拷贝(包括父类虚函数表指针和成员变量)。之后是子类自己的成员变量数据。 对于子类的子类,也是同样的原理。但是无论继承了多少个子类,对象中始终只有一个虚函数表指针。 为了探讨C++类对象的内存布局,先来写几个类和函数 首先写一个基类: { public: virtual void f { cout << “Base::f” << endl; } virtual void g() { cout << “Base::g” << endl; } virtual void h() { cout << “Base::h” << endl; } int base; protected: private: }; 然后,我们多种不同的继承情况来研究子类的内存对象结构。 1. 无虚函数集继承 class Child1 : public Base { public: virtual void f1() { cout << “Child1::f1” << endl; } virtual void g1() { cout << “Child1::g1” << endl; } virtual void h1() { cout << “Child1::h1” << endl; } int child1; protected: private: }; 这个子类Child1没有继承任何一个基类的虚函数,因此它的虚函数表如下图: 我们可以看出,子类的虚函数表中,先存放基类的虚函数,在存放子类自己的虚函数, 2. 有一个虚函数继承 class Child2 : public Base { public: virtual void f() { cout << “Child2::f” << endl; } virtual void g2() { cout << “Child2::g2” << endl; } virtual void h2() { cout << “Child2::h2” << endl; } int child2; protected: private: }; 当子类重载了父类的虚函数,则编译器会将子类虚函数表中对应的父类的虚函数替换成子类的函数。 3. 全部虚函数都继承 class Child3 : public Base { public: virtual void f() { cout << “Child3::f” << endl; } virtual void g() { cout << “Child3::g” << endl; } virtual void h() { cout << “Child3::h” << endl; } protected: int x; private: }; 4. 多重继承 多重继承,即类有多个父类,这种情况下的子类的内存结构和单一继承有所不同。 我们可以看到,当子类继承了多个父类,那么子类的内存结构是这样的:子类的内存中,顺序 5. 菱形继承 6. 单一虚拟继承 虚拟继承的子类的内存结构,和普通继承完全不同。虚拟继承的子类,有单独的虚函数表, 另外也单独保存一份父类的虚函数表,两部分之间用一个四个字节的0x00000000来作为分界。子类的内存中,首先是自己的虚函数表,然后是子类的数据 成员,然后是0x0,之后就是父类的虚函数表,之后是父类的数据成员。 Swift中类和对象的属性分为三种:储存属性,计算属性和类属性, 看了MFC中的动态创建对象后,感觉动态创建对象算是一种技术吧,理论上说算是一种设计模式,其实创建的原理很明了,把对象的类别名称和其构造函数用容器记录下来,在需要的时候给出创建类别查找容器即可创建对象。当然这里我们需要自定义一个全局的函数指针用来指向类别的构造函数。在这里我们使用类工厂模式,在泪工厂中我们定义一个通用构造函数,将函数指针指向它。下面是参考一位网友思路来整理和摸索的代码: //通用的函数指针 typedef void *(*CREATE_FUNC); //创建类的工厂类 class DynObjectFactory{public: static void *CreateObject( const string &name) { map #define REGISTER_CLASS(class_name) \ class class_name##Register { \ public: \ static void* NewInstance() \ { return new class_name; } \ private: \ static Register reg_; \ }; \ Register class_name##Register::reg_(#class_name, class_name##Register::NewInstance) //CircleRegister //下面是测试类 *.h class Shape { public: virtual void Draw() = 0; virtual ~Shape() {} }; class Circle : public Shape { public: void Draw(); ~Circle(); }; class Square : public Shape { public: void Draw(); ~Square(); }; class Rectangle : public Shape { public: void Draw(); ~Rectangle(); }; //*.cpp void Circle::Draw() { cout << “Circle::Draw() ...” << endl; } Circle::~Circle() { cout << “~Circle ...” << endl; } void Square::Draw() { cout << “Square::Draw() ...” << endl; } Square::~Square() { cout << “~Square ...” << endl; } void Rectangle::Draw() { cout << “Rectangle::Draw() ...” << endl; } Rectangle::~Rectangle() { cout << “~Rectangle ...” << endl; } REGISTER_CLASS(Circle); REGISTER_CLASS(Square); REGISTER_CLASS(Rectangle); //main.cpp void DrawAllShapes( const vector { vector for (it = v.begin(); it != v.end(); ++it) { (*it)->Draw(); } } void DeleteAllShapes( const vector { vector for (it = v.begin(); it != v.end(); ++it) { delete(*it); } } int main( void) { vector Shape *ps; ps = static_cast v.push_back(ps); ps = static_cast v.push_back(ps); ps = static_cast v.push_back(ps); DrawAllShapes(v); DeleteAllShapes(v); return 0; } 这篇文章主要介绍了Python检测一个对象是否为字符串类的方法,即检测是一个对象是否是字符串对象,本文还讲解了一个有趣的判断方法,需要的朋友可以参考下 目的 测试一个对象是否是字符串 方法 Python的字符串的基类是basestring,包括了str和unicode类型,一般可以采用以下方法: 代码如下: def isAString(anobj): return isinstance(anobj,basestring) 不过以上方法对于UserString类的实例,无能无力。 代码如下: In [30]: b=UserString.UserString(‘abc‘) In [31]: isAString(b) Out[31]: False In [32]: type(b) Out[32]: Python中常用的鸭子判断法:如果它走路像鸭子,叫声像鸭子,就可以认为它是鸭子了。 代码如下: def isStringLike(anobj): try: anobj.lower() + anobj + ‘ ‘ except: return False else: return True 测试结果如下: 代码如下: >>>import UserString >>>b=UserString.UserString(‘abc‘) >>>isStringLike(b) True >>> 关于风格 根据自己的语气去执行任务,在此过程中检测并处理由于不匹配产生的所有错误和异常, 这种处理方式称为: 代码如下: EAFP:It‘s easier to ask forgiveness than permission. try/except是保证该风格的关键工具。 八卦一下,关于UserString类 对于2.X版本:Python文档中提到,如果不涉及到2.2以前的版本,请考虑直接使用str类型来代替UserString类型。 对于3.X版本:该模块已经移到collection模块中。 该类主要有两种方法: 代码如下: class UserString.UserString([sequence]) 具体使用前面已经举例,注意可以使用str()转化为str类型 代码如下: class UserString.MutableString([sequence]) 字符串也可以变哦!Look here: 代码如下: a=UserString.MutableString(‘abc‘) a[0]=‘c‘ In [10]: a Out[10]: ‘cbc‘ Python文档上有行黑体字,原来已经是弃用的方法,3.0就没有了: 代码如下: Deprecated since version 2.6: The MutableString class has been removed in Python 3.0. 局部变量和成员变量重名的情况下,局部变量会隐藏成员变量, 为了在方法中强行引用成员变量,可以使用 self 关键字进行区分。 示例代码: FKWolf.h文件 FKWolf.m 文件 当 self 作为对象的默认引用使用时,程序可以像访问普通指针变量一样访问这个 self引用,甚至可以把 self 当成普通方法的返回值。 示例程序: ReturnSel.m文件 说明:使用 self 作为方法的返回值可以使代码更加简洁,但可能造成实际意义的模糊。 id 类型可以代表所有对象的类型。任意类的对象都可赋值给 id 类型的变量。 通过 id 类型的变量来调用方法时,objective-c 将会执行动态绑定。动态绑定:objective-c 将会跟踪对象所属的类,会在运行时判断该对象所属的类,并在运行时确定需要动态调用的方法,而不是在编译时确定要调用的方法。 示例程序: Python是一个完全面向对象的语言。不仅实例是对象,类,函数,方法也都是对象。 代码如下: class Foo(object): static_attr = True def method(self): pass foo = Foo() 这段代码实际上创造了两个对象,Foo和foo。而Foo同时又是一个类,foo是这个类的实例。 在C++里类型定义是在编译时完成的,被储存在静态内存里,不能轻易修改。在Python里类型本身是对象,和实例对象一样储存在堆中,对于解释器来说类对象和实例对象没有根本上的区别。 在Python中每一个对象都有自己的命名空间。空间内的变量被存储在对象的__dict__里。这样,Foo类有一个__dict__, foo实例也有一个__dict__,但这是两个不同的命名空间。 所谓“定义一个类”,实际上就是先生成一个类对象,然后执行一段代码,但把执行这段代码时的本地命名空间设置成类的__dict__. 所以你可以写这样的代码: 代码如下: >>>class Foo(object): ... bar = 1 + 1 ... qux = bar + 1 ... print “bar: ”, bar ... print “qux: ”, qux ... print locals() ... bar: 2 qux: 3 {‘qux‘: 3, ‘__module__‘: ‘__main__‘, ‘bar‘: 2} >>>print Foo.bar, Foo.__dict__[‘bar‘] 2 2 >>>print Foo.qux, Foo.__dict__[‘qux‘] 3 3 所谓“定义一个函数”,实际上也就是生成一个函数对象。而“定义一个方法”就是生成一 个函数对象,并把这个对象放在一个类的__dict__中。下面两种定义方法的形式是等价的: 代码如下: >>>class Foo(object): ... def bar(self): ... return 2 ... >>>def qux(self): ... return 3 ... >>>Foo.qux = qux >>>print Foo.bar, Foo.__dict__[‘bar‘] >>>print Foo.qux, Foo.__dict__[‘qux‘] >>>foo = Foo() >>>foo.bar() 2 >>>foo.qux() 3 而类继承就是简单地定义两个类对象,各自有不同的__dict__: 代码如下: >>>class Cheese(object): ... smell = ‘good‘ ... taste = ‘good‘ ... >>>class Stilton(Cheese): ... smell = ‘bad‘ ... >>>print Cheese.smell good >>>print Cheese.taste good >>>print Stilton.smell bad >>>print Stilton.taste good >>>print ‘taste‘ in Cheese.__dict__ True >>>print ‘taste‘ in Stilton.__dict__ False 复杂的地方在`.`这个运算符上。对于类来说,Stilton.taste的意思是“在Stilton.__dict__中找‘taste‘. 如果没找到,到父类Cheese的__dict__里去找,然后到父类的父类,等等。如果一直到object仍没找到,那么扔一个AttributeError.” 实例同样有自己的__dict__: 代码如下: >>>class Cheese(object): ... smell = ‘good‘ ... taste = ‘good‘ ... def __init__(self, weight): ... self.weight = weight ... def get_weight(self): ... return self.weight ... >>>class Stilton(Cheese): ... smell = ‘bad‘ ... >>>stilton = Stilton(‘100g‘) >>>print ‘weight‘ in Cheese.__dict__ False >>>print ‘weight‘ in Stilton.__dict__ False >>>print ‘weight‘ in stilton.__dict__ True 不管__init__()是在哪儿定义的, stilton.__dict__与类的__dict__都无关。 Cheese.weight和Stilton.weight都会出错,因为这两个都碰不到实例的命名空间。而 stilton.weight的查找顺序是stilton.__dict__ =>Stilton.__dict__ => Cheese.__dict__ =>object.__dict__. 这与Stilton.taste的查找顺序非常相似,仅仅是 在最前面多出了一步。 方法稍微复杂些。 代码如下: >>>print Cheese.__dict__[‘get_weight‘] >>>print Cheese.get_weight >>>print stilton.get_weight <__main__.Stilton object at 0x7ff820669190>> 我们可以看到点运算符把function变成了unbound method. 直接调用类命名空间的函数和点 运算返回的未绑定方法会得到不同的错误: 代码如下: >>>Cheese.__dict__[‘get_weight‘]() Traceback (most recent call last): File “”, line 1, in TypeError: get_weight() takes exactly 1 argument (0 given) >>>Cheese.get_weight() Traceback (most recent call last): File “”, line 1, in TypeError: unbound method get_weight() must be called with Cheese instance as first argument (got nothing instead) 但这两个错误说的是一回事,实例方法需要一个实例, 所谓“绑定方法”就是简单地在调用方法时把一个实例对象作为第一个参数。下面这些调用方法是等价的: 代码如下: >>>Cheese.__dict__[‘get_weight‘](stilton) ‘100g‘ >>>Cheese.get_weight(stilton) ‘100g‘ >>>Stilton.get_weight(stilton) ‘100g‘ >>>stilton.get_weight() ‘100g‘ 最后一种也就是平常用的调用方式,stilton.get_weight(),是点运算符的另一种功能,将stilton.get_weight()翻译成stilton.get_weight(stilton). 这样,方法调用实际上有两个步骤。首先用属性查找的规则找到get_weight, 然后将这个属性作为函数调用,并把实例对象作为第一参数。这两个步骤间没有联系。比如说你可以这样试: 代码如下: >>>stilton.weight() Traceback (most recent call last): File “”, line 1, in TypeError: ‘str‘ object is not callable 先查找weight这个属性,然后将weight做为函数调用。但weight是字符串,所以出错。要注意在这里属性查找是从实例开始的: 代码如下: >>>stilton.get_weight = lambda : ‘200g‘ >>>stilton.get_weight() ‘200g‘ 但是 代码如下: >>>Stilton.get_weight(stilton) ‘100g‘ Stilton.get_weight的查找跳过了实例对象stilton,所以查找到的是没有被覆盖的,在Cheese中定义的方法。 getattr(stilton, ‘weight‘)和stilton.weight是等价的。类对象和实例对象没有本质区别,getattr(Cheese, ‘smell‘)和Cheese.smell同样是等价的。getattr()与点运算符相比,好处是属性名用字符串指定,可以在运行时改变。 __getattribute__()是最底层的代码。如果你不重新定义这个方法,object.__getattribute__()和type.__getattribute__()就是getattr()的具体实现,前者用于实例,后者用以类。换句话说,stilton.weight就是object.__getattribute__(stilton, ‘weight‘). 覆盖这个方法是很容易出错的。比如说点运算符会导致无限递归: 代码如下: def __getattribute__(self, name): return self.__dict__[name] __getattribute__()中还有其它的细节,比如说descriptor protocol的实现,如果重写很容易搞错。 __getattr__()是在__dict__查找没找到的情况下调用的方法。一般来说动态生成属性要用这个,因为__getattr__()不会干涉到其它地方定义的放到__dict__里的属性。 代码如下: >>>class Cheese(object): ... smell = ‘good‘ ... taste = ‘good‘ ... >>>class Stilton(Cheese): ... smell = ‘bad‘ ... def __getattr__(self, name): ... return ‘Dynamically created attribute “%s”‘ % name ... >>>stilton = Stilton() >>>print stilton.taste good >>>print stilton.weight Dynamically created attribute “weight” >>>print ‘weight‘ in stilton.__dict__ False 由于方法只不过是可以作为函数调用的属性,__getattr__()也可以用来动态生成方法,但同样要注意无限递归: 代码如下: >>>class Cheese(object): ... smell = ‘good‘ ... taste = ‘good‘ ... def __init__(self, weight): ... self.weight = weight ... >>>class Stilton(Cheese): ... smell = ‘bad‘ ... def __getattr__(self, name): ... if name.startswith(‘get_‘): ... def func(): ... return getattr(self, name[4:]) ... return func ... else: ... if hasattr(self, name): ... return getattr(self, name) ... else: ... raise AttributeError(name) ... >>>stilton = Stilton(‘100g‘) >>>print stilton.weight 100g >>>print stilton.get_weight >>>print stilton.get_weight() 100g >>>print stilton.age Traceback (most recent call last): File “”, line 1, in File “”, line 12, in __getattr__ AttributeError: age 希望本文所述对大家的Python程序设计有所帮助。 【初始化类对象】相关文章: 1.汇报对象 2.入党对象现实表现 3.政审对象现实表现 4.检讨书 处对象 5.教学对象分析 6.对象考察材料 7.教育叙事对象 9.IOS 开发学习总结 objectivec面向对象之――类和对象(下) 10.向相亲对象自我介绍篇2:Effective C++ 确定对象被使用前已先被初始化
电脑资料
篇3:c++类对象的内存模型
class Base
//子类1,无虚函数重载
//子类2,有1个虚函数重载
//子类3,全部虚函数重载
篇4:Swift面向对象中类和对象的属性
import Foundationclass Person { // 储存属性必须赋初值 var score1: Int = 20 var score2: Int = 50 // 延迟储存属性,需要时再去分配 lazy var dog: Dog = Dog() // 计算属性,不能赋初值,提供get和set方法, var sum: Int { get {return score1 + score2 } } // 类属性,只能是计算属性,使用类而非对象去调用 // 如 Person.desc class var desc: String { get {return This is one person. } } // 构造方法 init() { println(This is one person.) }}class Dog { init() { println(This is one dog.) }}var p = Person()println(Person.desc)println(p.score1)println(p.score2)println(p.sum)println(p.dog)
篇5:C++ 类工厂实现动态对象创建
篇6:Python检测一个对象是否为字符串类的方法
篇7:IOS 开发学习总结 objectivec面向对象之――类和对象(下)
#import
#import FKWolf.h@implementation FKWolf// 定义一个setName:ageAge方法- (void) setName: (NSString*) _name andAge: (int) _age{ // 当局部变量隐藏成员变量时, // 可用self代表调用该方法的对象,这样即可为调用该方法的成员变量赋值了。 self->_name = _name; self->_age = _age;}// 定义一个info方法- (void) info{ NSLog(@我的名字是%@, 年龄是%d岁 , _name , _age);}@endint main(int argc , char * argv[]) { @autoreleasepool{ FKWolf* w = [[FKWolf alloc] init]; [w setName: @灰太狼 andAge:8]; [w info]; }}
篇8:IOS 开发学习总结 objectivec面向对象之――类和对象(下)
#import
id 类型
#import
篇9:Python中的对象,方法,类,实例,函数用法分析






文档为doc格式