C ++ interview

Source: Internet
Author: User
Question (1): In C ++, we can use static to modify the member functions of a class, or use const to modify the member functions of the class (written at the end of the function to indicate that the member variables cannot be modified, it does not mean that the return value is a constant ). Can I modify the member functions of the class with both static and const? Analysis: the answer is no. When implementing a const member function, the C ++ compiler adds an implicit parameter const this * to ensure that the function cannot modify the instance status of the class *. But when a Member is static, this function does not have the this pointer. In other words, static usage conflicts with static usage. We can also understand that the meanings of the two are contradictory. Static indicates that the function only applies to static variables of the type and has no relationship with the instance of the class. Const ensures that the function cannot modify the instance status of the class, it has nothing to do with the type of static variables. Therefore, they cannot be used at the same time. Question (2): run the following C ++ code. What is output? Class A {}; Class B {public: B (){}~ B () {}}; class c {public: C () {}virtual ~ C () {}}; int _ tmain (INT argc, _ tchar * argv []) {printf ("% d, % d, % d/N ", sizeof (A), sizeof (B), sizeof (c); Return 0;} analysis: the answer is 1, 1, 4. Class A is an empty type, and its instance does not contain any information. Originally, sizeof should be 0. But when we declare this type of instance, it must occupy a certain amount of space in the memory, otherwise these instances cannot be used. The compiler determines how much memory is used. In Visual Studio 2008, each empty instance occupies one byte space. Class B adds constructor and destructor Based on Class. The call of constructor and destructor is independent of the Instance type (you only need to know the function address to call them), so no information is required in the instance. So sizeof (B) is the same as sizeof (A), and is 1 in Visual Studio 2008. Class C marks the Destructor as a virtual function based on Class B. The C ++ compiler generates a virtual function table for a type that contains virtual functions, and adds a pointer to the virtual function table to each instance of the type. On a 32-bit machine, a pointer occupies 4 bytes of space, so sizeof (c) is 4. Question (3): run the following C ++ code. What is the result? Class A {PRIVATE: int m_value; public: A (INT value) {m_value = value;} void print1 () {printf ("Hello World");} void print2 () {printf ("% d", m_value) ;}; int _ tmain (INT argc, _ tchar * argv []) {A * pA = NULL; pa-> print1 (); pa-> print2 (); Return 0;} analysis: the answer is that print1 is called normally and hello World is printed. However, when print2 is run, the program crashes. When you call print1, you do not need the PA address because the function address of print1 is fixed. The compiler will pass in a this pointer to print1, Which is null, but this pointer is not used in print1. As long as the program is running without accessing the memory that shouldn't be accessed, no error occurs, so it runs normally. When running print2, this pointer is required to obtain the m_value value. The program crashes because this pointer is null. Question (4): run the following C ++ code. What is the result? Class A {PRIVATE: int m_value; public: A (INT value) {m_value = value;} void print1 () {printf ("Hello World");} virtual void print2 () {printf ("Hello World") ;}}; int _ tmain (INT argc, _ tchar * argv []) {A * pA = NULL; pa-> print1 (); pa-> print2 (); Return 0;} analysis: the answer is that print1 is called normally and hello World is printed. But when print2 is run, the program crashes. The call of print1 is the same as that of the previous question. Because print2 is a virtual function. When calling a virtual function, C ++ obtains the virtual function table based on the virtual function table pointer in the instance (that is, the instance pointed to by this pointer), and finds the function address from the virtual function table. Because this step needs to access the instance address (that is, the this pointer), and this pointer is a null pointer, this causes memory access errors. Question (5): Can static member functions in C ++ be also virtual functions? Analysis: the answer is no. Do not call static member functions for instances. However, to call a virtual function, you need to point a pointer to the virtual function table from an instance to obtain the address of the function. Therefore, you need an instance to call the virtual function. The two are in conflict. Question (6): run the following C ++ code and output what? Struct point3d {int X; int y; int Z ;}; int _ tmain (INT argc, _ tchar * argv []) {point3d * Ppoint = NULL; int offset = (INT) (& (Ppoint)-> Z); printf ("% d", offset); Return 0 ;}answer: Output 8. Because the address is added to the front of Ppoint-> Z, when running, the offset of Z in the point3d type is added to the pointer address of Ppoint. Because the Ppoint address is 0, the final offset value is 8. & (Ppoint-> Z) indicates the address of the variable Z in Ppoint (Ppoint address 0 and Z offset 8), and does not need to access the memory pointed to by Ppoint. As long as you do not access the invalid memory, the program will not go wrong. Question (7): run the following C ++ code and output what? Class A {public: A () {print ();} virtual void print () {printf ("A is constructed. /n ") ;}}; Class B: Public A {public: B () {print ();} virtual void print () {printf (" B is constructed. /n ") ;}}; int _ tmain (INT argc, _ tchar * argv []) {A * pA = new B (); Delete Pa; return 0 ;} answer: two rows are printed successively: A is constructed. B is constructed. when calling the constructor of B, it first calls the base class of B and the constructor of. Then, print is called in the constructor. At this time, because the part of instance type B has not been properly constructed, it is essentially only an instance of a, and its virtual function table Pointer Points to the virtual function table of type. Therefore, print is called as a: Print instead of B: print. Next, call the constructor of type B and call print. At this time, B has been constructed, so the called print is B: print. We also call the virtual function print. We found that in the constructor of type A, A: print is called. In the constructor of type B, B: print is called. Therefore, the dynamic binding feature of virtual functions has been lost in constructors. Question (8): run the following C # code. What is output? Namespace changesonstring {class program {static void main (string [] ARGs) {string STR = "hello"; Str. toupper (); Str. insert (0, "world"); console. writeline (STR) ;}} answer: the output is hello. In. net, string has a special property: the status of the string instance cannot be changed. If the string member function modifies the instance status, a new string instance is returned. Changes will only appear in the return value, but will not change the original Instance. Therefore, the output in this question is still the original string value hello. If you try to change the string content, you can obtain the changed value through the return value. Using stringbuilder is a better choice, especially when it needs to be modified multiple times in a row. If the string is used for multiple consecutive modifications, each modification generates a temporary object with a high overhead. Question (9): What is the difference between struct and class in C ++ and C? Answer: In C ++, if the access permission level of the function or variable is not indicated, it is public in struct, while private in class. In C #, if the access permission level of the function or variable is not specified, both struct and class are private. The difference between struct and class is that struct defines the value type, and its instance allocates memory on the stack; class defines the reference type, and its instance allocates memory on the stack. Question (10): In the running C # code, what is output? Namespace staticconstructor {Class A {public a (string text) {console. writeline (text) ;}} Class B {static A a1 = new A ("A1"); A a2 = new A ("A2"); static B () {a1 = new A ("A3");} public B () {a2 = new A ("A4 ");}} class program {static void main (string [] ARGs) {B = new B () ;}} answer: print out four rows, a1, A3, A2, and A4. Execute the static constructor of B before calling the code of type B. Static functions initialize static variables and then execute statements in static functions. Therefore, print A1 first and then A3. Next, execute B = new B (), that is, call the normal constructor of B. The constructor first initializes the member variables and executes the statements in the function body. Therefore, A2 and A4 are printed successively. Question (11): In the running C # code, what is the output? Namespace stringvalueorreference {class program {internal static void valueorreference (type) {string result = "the type" + type. name; If (type. isvaluetype) console. writeline (result + "is a value type. "); else console. writeline (result + "is a reference type. ");} internal static void modifystring (string text) {text =" world ";} static void main (string [] ARGs) {string text =" hello "; valu Eorreference (text. GetType (); modifystring (text); console. writeline (text) ;}} answer: two rows are output. The first line is the type string is reference type. The second line is hello. The string type is defined as public sealed class string {...}. Since it is a class, string is the reference type. In the modifystring method, assign a new string to text, instead of the original text content, but point text to a new string "world ". Since the text parameter does not contain ref or out, after the method is output, the text still points to the original string, so the output is still "hello ". question (12): What is the output of the running C ++ code? # Include <iostream> Class A {PRIVATE: int N1; int N2; public: A (): N2 (0), N1 (n2 + 2) {} void print () {STD: cout <"N1:" <N1 <", N2:" <N2 <STD: Endl ;}}; int _ tmain (INT argc, _ tchar * argv []) {A;. print (); Return 0;} answer: the output N1 is a random number, and N2 is 0. In C ++, the initialization sequence of member variables is the same as the declarative sequence of variables in the type, but it is irrelevant to the sequence in the initialization list of the constructor. Therefore, in this question, N1 is initialized first, while N2, the initial N1 parameter, is a random value. Therefore, N1 is a random value. When N2 is initialized, It is initialized according to the parameter 0, so n2 = 0. Question (13): Compile the running C ++ code. What is the result? (A) Compilation error; (B) successful compilation, program crash during running; (c) normal compilation and 10 output. Select the correct answer and analyze the cause. # Include <iostream> Class A {PRIVATE: int value; public: A (int n) {value = N;} A (a other) {value = Other. value;} void print () {STD: cout <value <STD: Endl ;}; int _ tmain (INT argc, _ tchar * argv []) {A = 10; a B = A; B. print (); Return 0;} answer: Compilation error. The input parameter in the copy constructor is an instance of. The copy constructor is called to copy the form parameter to the real parameter. Therefore, if the copy constructor is allowed to pass values, an endless recursion will be formed and stack overflow will occur. Therefore, the C ++ standard does not allow copying constructors to pass value parameters. Instead, it must be a reference or constant reference. In Visual Studio and GCC, compilation errors occur. Question (14): What is the output of the running C ++ code? Int sizeof (char pstring []) {return sizeof (pstring);} int _ tmain (INT argc, _ tchar * argv []) {char * pstring1 = "google "; int size1 = sizeof (pstring1); int size2 = sizeof (* pstring1); char pstring2 [100] = "google"; int size3 = sizeof (pstring2 ); int size4 = sizeof (pstring2); printf ("% d, % d", size1, size2, size3, size4); Return 0;} answer: 4, 1,100, 4. Pstring1 is a pointer. On 32-bit machines, any pointer occupies 4 bytes of space. * Pstring1 is the first character of the string pstring1. A character occupies one byte. Pstring2 is an array, and sizeof (pstring2) is used to evaluate the size of the array. The array contains 100 characters, so the size is 100 bytes. In the sizeof function, although the input parameter is a character array, when the array is passed as a function parameter, the array will automatically degrade to the same type of pointer. Therefore, size4 is also the pointer size. It is 4. Question (15): What is the output result of the running code? What is the problem with this code? # Include <iostream> Class A {public: A () {STD: cout <"A is created." <STD: Endl ;}~ A () {STD: cout <"A is deleted. "<STD: Endl ;}; Class B: Public A {public: B () {STD: cout <" B is created. "<STD: Endl ;}~ B () {STD: cout <"B is deleted. "<STD: Endl ;}; int _ tmain (INT argc, _ tchar * argv []) {A * pA = new B (); Delete Pa; return 0;} answer: output three rows: A is created. B is created. A is deleted. When B is created with new, the constructor B is called back. When calling the constructor of B, the constructor of A is called first. Therefore, output A is created. B is created. When the delete statement is run, the Destructor is called. Since PA is declared as a pointer of type A, and the destructor of base class A is not labeled as virtual, only the destructor of Class A is called, instead of calling the destructor of B. Since PA is actually a pointer to a B instance, only the destructor of the base class A is called during the analysis, but the destructor of B is not called. This is a problem. If some resources, such as file handle and memory, are created in type B, they are not released, resulting in resource leakage. Question (16): run the following C ++ code. What is the output? Class A {public: Virtual void fun (INT number = 10) {STD: cout <"A: Fun with number" <number ;}}; Class B: public A {public: Virtual void fun (INT number = 20) {STD: cout <"B: Fun with number" <number ;}}; int main () {B; A & A = B;. fun () ;}answer: Output B: Fun with number 10. Because a is a reference to B instance, B: Fun is called during running. However, the default parameters are determined during the compilation period. During compilation, the compiler only knows that A is a reference of type A. The specific type pointed to cannot be determined during the compilation period. Therefore, :: fun's statement sets the default parameter number to 10. The key to this question is to understand how to determine the default parameter value during compilation, but to determine which type of function is called by the referenced or pointer virtual function. Question (17): run the following C code. What is the output? Char * getstring1 () {char P [] = "Hello World"; return P;} Char * getstring2 () {char * P = "Hello World"; return P ;} int _ tmain (INT argc, _ tchar * argv []) {printf ("getstring1 returns: % S. \ n ", getstring1 (); printf (" getstring2 returns: % S. \ n ", getstring2 (); Return 0;} answer: two rows are output. The first row, getstring1 returns: Followed by a random string of content, the second line is getstring2 returns: Hello world. the difference between the two functions is that getstring1 is an array and getstring2 is a pointer. When running to getstring1, P is an array that opens up a piece of memory and copies "Hello World" to initialize the array. Return the first address of the array and exit the function. Since P is a local variable in getstring1, the memory of this array will be released when it runs outside the function. Therefore, when accessing the content of this array in the _ tmain function, the result is random. When running to getstring2, P is a pointer pointing to a constant string in the String constant area. The constant string is global and will not be released because it exits the getstring2 function. Therefore, in _ tmain, the string "Hello world" is still obtained based on the address returned by getstring2 ". Question (18): In the running C # code, what is the output result? Namespace staticvariableinappdomain {[serializable] internal class A: externalbyrefobject {public static int number; Public void setnumber (INT value) {number = value ;}} [serializable] internal class B {public static int number; Public void setnumber (INT value) {number = value ;}} class program {static void main (string [] ARGs) {string assamblyname = assembly. getentryassembly (). fullname; app Domain domain = appdomain. createdomain ("newdomain");. number = 10; string nameofa = typeof (). fullname; A = domain. createinstanceandunwrap (assamblyname, nameofa) as a;. setnumber (20); console. writeline ("number in Class A is {0}",. number); B. number = 10; string nameofb = typeof (B ). fullname; B = domain. createinstanceandunwrap (assamblyname, nameofb) as B; B. setnumber (20); console. writeline ("n Umber in Class B is {0} ", B. number) ;}} answer: two rows are output. The first row is number in Class A is 10, and the second row is number in Class B is 20. The above C # code first creates an application domain named newdomain, and uses the reflection mechanism in this domain to create an instance of type A and an instance of type B. We noticed that type A inherits from marshalbyrefobject, while Type B does not. Although the two types have the same structure, the behavior displayed when crossing the boundaries of the application domain varies greatly due to different base classes. Because a inherits marshalbyrefobject, A actually only acts as a proxy in the default domain. It points to an instance of a in the newdomain domain. When a. setnumber is called in the newdomain domain, it modifies the value of static variable A. number in the newdomain domain and sets it to 20. Because static variables have an independent copy in each application domain, modifying the static variable A. number in the newdomain domain has no effect on the static variable A. newdomain in the default domain. Because console. writeline Outputs A. number in the default application domain, the output is still 10. B only inherits the type from the object. When its instance crosses the boundary of the application domain, it will completely copy the instance. In the above Code, although we try to generate B's instance in the newdomani domain, we will copy instance B to the default domain. In this case, the call to B. setnumber is also performed on the default domain. It modifies a. number on the default domain and sets it to 20. Therefore, this output is 20. Question (19): What is the output result of running C code? Int _ tmain (INT argc, _ tchar * argv []) {char str1 [] = "Hello World"; char str2 [] = "Hello World "; char * str3 = "Hello World"; char * str4 = "Hello World"; if (str1 = str2) printf ("str1 and str2 are same. \ n "); else printf (" str1 and str2 are not same. \ n "); If (str3 = str4) printf (" str3 and str4 are same. \ n "); else printf (" str3 and str4 are not same. \ n "); Return 0;} answer: two rows are output. The first line is str1 and str2 are not same, and the second line is str3 and str4 are same. Str1 and str2 are two string arrays. We will allocate two 12-byte spaces for them, and copy the "Hello World" contents to the array respectively. These are two arrays with different initial addresses. Therefore, the values of str1 and str2 are different. Str3 and str4 are two pointers. Instead of allocating memory to them to store string content, we only need to point them to the address in the memory of "Hello World. Because "Hello world" is a constant string and has only one copy in the memory, str3 and str4 point to the same address. Therefore, comparing str3 and str4 values is the same. Question (20): In the running C # code, what is the output result? Compare the characteristics and differences between the two types. Namespace Singleton {public sealed class singleton1 {private singleton1 () {console. writeline ("singleton1 constructed");} public static void print () {console. writeline ("singleton1 print");} Private Static singleton1 instance = new singleton1 (); public static singleton1 instance {get {return instance ;}} public sealed class singleton2 {singleton2 () {console. writeline ("singleton2 construct Ed ");} public static void print () {console. writeline ("singleton2 print");} public static singleton2 instance {get {return nested. instance ;}} class nested {static nested () {} internal static readonly singleton2 instance = new singleton2 () ;}} class program {static void main (string [] ARGs) {singleton1.print (); singleton2.print () ;}} answer: output three rows: singleton1 constructed in the first line, and singleton1 PR in the second line Int, the third line is "singleton2 print ". When we call singleton1.print,. Net automatically calls the static constructor of singleton1 during runtime and initializes its static variables. A singleton1 instance is created, and its constructor is called. Singleton2 instances are initialized in the static constructor of nested. Only when the type of nested is used can the static constructor called when. NET is triggered. We noticed that we only used nested in sington2.instance. In our code, only singleton2.print is called. Therefore, the singleton2 instance will not be created or its constructor will not be called. These two types are actually implemented by Singleton. The second implementation of singleton2 will create an instance only when it is really needed, but the first implementation of singleton1 will not. The second is to achieve better space efficiency.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.